(要熟练!)
题目大意
输入一个结点序列,按照这个序列输入,每插入一次都自动调整为平衡二叉搜索树AVL。求最终形成的AVL树根的值。
在AVL树中,任何节点的两个子子树的高度最多相差一个;如果在任何时候它们相差多于一个,则重新平衡以恢复此属性。
思路
熟练掌握建立AVL的代码即可。
坑
在判断子结点平衡因子的时候,为1和为-1两个if必须是互斥的。一开始没写else,会出现进入第一个if后平衡因子的值改变了又进入第二个if的情况。
debug了一早上,一直以为是别的问题,没注意到这个细节...但发现可以不必在结构体中保存每个结点的高度,需要判断的时候每次递归求解即可。
建立树的过程还不够熟练,一定要多多再写几遍。
AC代码
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include <cstdio>
#include <vector>
#include <map>
#include<algorithm>
#include<queue>
using namespace std;
struct node {
int key;
node* lchild, * rchild;
};
int getheight(node* root) {
if (root == NULL)return 0;
return max(getheight(root->lchild), getheight(root->rchild)) + 1;
}
int balance(node* root) {
return getheight(root->lchild) - getheight(root->rchild);
}
void R(node*& root) {
node* newroot = root->lchild;
root->lchild = newroot->rchild;
newroot->rchild = root;
root = newroot;
}
void L(node*& root) {
node* newroot = root->rchild;
root->rchild = newroot->lchild;
newroot->lchild = root;
root = newroot;
}
void insert(node*& root, int number) {
if (root == NULL) {
root = new node;//注意细节
root->key = number;
root->lchild = root->rchild = NULL;
return;
}
if (number < root->key) {
insert(root->lchild, number);
if (balance(root) == 2) {
if (balance(root->lchild) == 1)R(root);
//一开始漏了“else”,可能出现进入上一个1的if后值改变了又进入第二个if的情况
else if (balance(root->lchild) == -1) {
L(root->lchild);
R(root);
}
}
}
else {
insert(root->rchild, number);
if (balance(root) == -2) {
if (balance(root->rchild) == -1)L(root);
else if (balance(root->rchild) == 1) {
R(root->rchild);
L(root);
}
}
}
}
int main() {
int i, n;
scanf("%d", &n);
int number;
node* root = NULL;
for (i = 0;i < n;i++) {
scanf("%d", &number);
insert(root, number);
}
printf("%d", root->key);
return 0;
}
最后附上一个按照算法笔记上写的(在节点中加入了参数height表示该结点的高度)代码
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include <cstdio>
#include <vector>
#include <map>
#include<algorithm>
#include<queue>
using namespace std;
struct node {
int key;
node* lchild, * rchild;
int height;
};
int getheight(node* p) {
if (p == NULL)return 0;
return p->height;
}
int balance(node* root) {
return getheight(root->lchild) - getheight(root->rchild);
}
void updateheight(node* root) {
root->height = max(getheight(root->lchild), getheight(root->rchild)) + 1;
}
void R(node*& root) {
node* newroot = root->lchild;
root->lchild = newroot->rchild;
newroot->rchild = root;
updateheight(root);//记得更新高度!而且这里必须先更新root(因为它现在是newroot孩子)!
updateheight(newroot);
root = newroot;
}
void L(node*& root) {
node* newroot = root->rchild;
root->rchild = newroot->lchild;
newroot->lchild = root;
updateheight(root);//记得更新高度!
updateheight(newroot);
root = newroot;
}
void insert(node*& root, int number) {
if (root == NULL) {
root = new node;//注意细节
root->height = 1;
root->key = number;
root->lchild = root->rchild = NULL;
return;
}
if (number <= root->key) {
insert(root->lchild, number);
updateheight(root);
if (balance(root) == 2) {
if (balance(root->lchild) == 1)R(root);
else if (balance(root->lchild) == -1) {
L(root->lchild);
R(root);
}
}
}
else {
insert(root->rchild, number);
updateheight(root);
if (balance(root) == -2) {
if (balance(root->rchild) == -1)L(root);
else if (balance(root->rchild) == 1) {
R(root->rchild);
L(root);
}
}
}
}
int main() {
int i, n;
scanf("%d", &n);
int number;
node* root = NULL;
for (i = 0;i < n;i++) {
scanf("%d", &number);
insert(root, number);
}
printf("%d", root->key);
return 0;
}