概念与特性
AVL树是期每个节点的左子树和右子树的高度最多相差1的二叉查找树。
对于一颗高度为h的AVL树而言,最少节点数 S ( h ) S(h) S(h)= S ( h − 1 ) S(h-1) S(h−1)+ S ( h − 2 ) S(h-2) S(h−2)+1。对于h=0, S ( h ) = 1 S(h)=1 S(h)=1;对于h=1, S ( h ) = 2 S(h)=2 S(h)=2。
基本操作
对于AVL树而言,插入一个节点,可能会破坏AVL树的特性。如果发生了这种情况,为了保证其特性,我们需要对其进行一些修正操作。我们将这个操作称之为旋转(rotation)。
我们把需要平衡的结点称之为a,这种不平衡,有以下四种情况:
1.对a的左儿子的左子树进行了一次插入操作;
2.对a的左儿子的右子树进行了一次插入操作;
3.对a的右儿子的右子树进行了一次插入操作;
4.对a的右儿子的左子树进行了一次插入操作;
对于左-左或者右-右情形,我们可以采用单旋转进行调整,对于左-右或者右-左情形,我们需要采用双旋转进行调整。
单旋转
AVLtree* SingerotateWihtleft(AVLtree* T) {
AVLtree* T1;
T1 = T->lchild;
T->lchild = T1->rchild;
T1->rchild = T;
T->height = max(returnHeight(T->lchild), returnHeight(T->rchild)) + 1;
T1->height = max(returnHeight(T1->lchild), T->height) + 1;
return T1;
}
AVLtree* SingerotateWihtright(AVLtree* T) {
AVLtree* T1;
T1 = T->rchild;
T->rchild = T1->lchild;
T1->lchild = T;
T->height = max(returnHeight(T->lchild), returnHeight(T->rchild)) + 1;
T1->height = max(returnHeight(T1->rchild), T->height) + 1;
return T1;
}
双旋转
AVLtree* DoublerotateWihtleft(AVLtree* T) {
T->lchild = SingerotateWihtright(T->lchild);
return SingerotateWihtleft(T);
}
AVLtree* DoublerotateWihtright(AVLtree* T) {
T->rchild = SingerotateWihtleft(T->rchild);
return SingerotateWihtright(T);
}
有了以上单旋转和双旋转的调整操作后,我们就可以写出AVL树的插入操作了
插入操作
AVLtree* insertNode(AVLtree* T,int x) {
if (T == NULL) {
T = new AVLtree;
if (T == NULL) exit(1);
else {
T->data = x; T->height = 0;
T->lchild = NULL; T->rchild = NULL;
}
}
else if (x < T->data) {
T->lchild = insertNode(T->lchild, x);
if (returnHeight(T->lchild) - returnHeight(T->rchild) == 2) {
if (x < T->lchild->data)
T = SingerotateWihtleft(T);
else
T = DoublerotateWihtleft(T);
}
}
else if (x > T->data) {
T->rchild = insertNode(T->rchild, x);
if (returnHeight(T->rchild) - returnHeight(T->lchild) == 2) {
if (x > T->rchild->data)
T = SingerotateWihtright(T);
else
T = DoublerotateWihtright(T);
}
}
return T;
}
删除操作
与普通二叉查找树几乎一样,不过要多一个更新操作,以免破坏树的平衡。
AVLtree* DeleteNode(AVLtree* T, int num) {
AVLtree* temp = NULL;
if (T == NULL) cout << "NO data" << endl;
else if (num < T->data)
T->lchild = DeleteNode(T->lchild, num);
else if (num > T->data)
T->rchild = DeleteNode(T->rchild, num);
else if (T->lchild && T->rchild) {
temp = FindMin(T);
T->data = temp->data;
T = DeleteNode(T->rchild, T->data);
}
else {
temp = T;
if (T->lchild == NULL)
T = T->rchild;
else if (T->rchild == NULL)
T = T->lchild;
free(temp);
}
if (T) {
int lheight = returnHeight(T->lchild), rheight = returnHeight(T->rchild);
T->height = (lheight > rheight ? lheight : rheight)+1;
if (lheight - rheight == 2) {
if (returnHeight(T->lchild->lchild) >= returnHeight(T->lchild->rchild))
T = SingerotateWihtleft(T);
else
T = DoublerotateWihtleft(T);
}
else if (rheight - lheight == 2) {
if (returnHeight(T->rchild->rchild) >= returnHeight(T->rchild->lchild))
T = SingerotateWihtright(T);
else
T = DoublerotateWihtright(T);
}
}
return T;
}
其他的操作,诸如,查找,寻找最小值,寻找最大值,输出等均与二叉查找树相同。