AVL的插入操作:找到所插位置之后,往上寻找可能发生不平衡之处x,若找到x则调整平衡。顶多调整平衡1次。
AVL的删除操作:找到删除结点x,类似于二叉查找树一样找到其后继或前驱y,若为x->right为NULL,y=x->lchild / x->rchild;否则找到x的后继,将x.key=y.key,x=x->right, key=y.key;循环此过程。后沿父结点一路向上调整。直到root为止。
源文件:avl_tree.h
#ifndef _AVL_TREE
#define _AVL_TREE
#define FALSE 0
#define TRUE 1
#define LH 1 // 左子树高
#define EH 0 // 等高
#define RH -1 // 右子树高
#define EQ(x, y) ((x)==(y)) // x==y
#define LT(x, y) ((x)<(y)) //x < y
typedef struct _TNode
{
int key;
int bf; //平衡因子
struct _TNode *left, *right;
} TNode, *PTNode;
#define TNODE_SIZE sizeof(TNode)
typedef PTNode AVLTree;
/* 将N个关键字插入AVL树当中. */
void insert_keys_to_AVL(AVLTree &tree, int keys[], int n);
/* 将关键字插入AVL树当中,taller为该树是否长高。返回值为是否成功插入。 */
int insert_key_to_AVL(AVLTree &tree, int key, int &taller);
/* 平衡由左子树超高引起的AVL树 */
void left_ballance(AVLTree &tree);
/* 平衡由右子树引起的AVL树 */
void right_ballance(AVLTree &tree);
/* 将tree绕左子树右下旋转~ */
void R_Rote(AVLTree &tree);
/* 将tree绕右子树左下旋转~ */
void L_Rote(AVLTree &tree);
/* 将含有关键字的结点删除,并重新调整至AVL树.lower标志是否变高。返回值若为1,则成功删除。0,则表示不在tree中 */
int delete_key_from_AVL(AVLTree &tree, int key,int &lower);
/* 显示AVL平衡树 */
void vist_tree_in_first(const AVLTree tree);
/* 释放AVL树 */
void destroy_tree(AVLTree tree);
#endif
avl_tree.cpp
#include "avl_tree.h"
#include <stdio.h>
#include <stdlib.h>
#include <iostream.h>
#include <assert.h>
void insert_keys_to_AVL(AVLTree &tree, int keys[], int n)
{
int taller = FALSE; // 此初值无影响
for(int i=0; i < n; i++)
{
insert_key_to_AVL(tree, keys[i], taller);
}
}
int insert_key_to_AVL(AVLTree &tree, int key, int &taller)
{
if(!tree)
{ // 插入新结点,如插入根结点,或叶子结点时(p->left = tree == null),且长高~
tree = (AVLTree)malloc(TNODE_SIZE);
tree->key = key;
tree->left = tree->right = NULL;
tree->bf = EH;
taller = TRUE;
}
else
{ // 当插入新结点之后,对于tree进行平衡处理
if(EQ(key, tree->key))
{ // 存在相同关键字,不需要进行插入
taller = FALSE;
return 0;
}
else if(LT(key, tree->key))
{ // 插入到左子树当中
// 如果由于已经存在相同关键字而没有成功插入到树当中~
if(!insert_key_to_AVL(tree->left, key, taller))
return 0;
if(taller) // 如果左子树变高了
{
switch(tree->bf)
{
// 如果左子树已经高1~,则需将左子树平衡~
case LH:
left_ballance(tree);taller = FALSE; break;
case EH:
tree->bf = LH; taller = TRUE; break;
case RH:
tree->bf = EH; taller = FALSE; break;
} // switch(tree->bf)
}
}
else
{// 右子树增高
// 如果由于已经存在相同关键字而没有成功插入到树当中~
if(!insert_key_to_AVL(tree->right, key, taller))
return 0;
if(taller) // 如果右子树变高了
{
switch(tree->bf)
{
case LH:
tree->bf = EH; taller = FALSE; break;
case EH: // 如果原左右子树相等,则左子树增加1,使得树“长高”
tree->bf = RH; taller = TRUE; break;
case RH: // 如果右子树已经高1~,现在又高1,则需将右子树平衡~
right_ballance(tree);taller = FALSE; break;
} // switch(tree->bf)
}
}
}
return 1;
}
void left_ballance(AVLTree &tree)
{
PTNode lc, lrc;
lc = tree->left;
switch(lc->bf)
{
case EH:
tree->bf = LH; lc->bf = RH; R_Rote(tree);break;
case LH:
tree->bf = lc->bf = EH; R_Rote(tree); break;
case RH:
lrc = tree->left->right;
switch(lrc->bf)
{
case LH:
lc->bf = EH; tree->bf = RH;break;
case EH:
lc->bf =tree->bf = EH; break;
case RH:
tree->bf = EH; lc->bf = LH; break;
} // switch(lrc->bf)
lrc->bf = EH;
L_Rote(tree->left); // 不可以写成 L_Rote(lrc);为什么?因为若为此,则改变的是lrc指针变量的值,而非tree->left.
R_Rote(tree);
break;
} // switch(left->bf)
}
void right_ballance(AVLTree &tree)
{
PTNode rc, rlc; // rc为tree的右结点,rlc为rc的左结点
rc = tree->right;
switch(rc->bf)
{
case EH:
tree->bf = RH; rc->bf = LH; L_Rote(tree);break;
case RH:
tree->bf = rc->bf = EH; L_Rote(tree); break;
case LH:
rlc = rc->left;
switch(rlc->bf)
{
case LH:
tree->bf = EH; rc->bf = RH;break;
case EH:
tree->bf = rc->bf = EH; break;
case RH:
tree->bf = LH; rc = EH; break;
}
rlc->bf = EH;
R_Rote(tree->right);
L_Rote(tree);
break;
}
}
void R_Rote(AVLTree &tree)
{
PTNode lc;
lc = tree->left;
tree->left = lc->right;
lc->right = tree;
tree = lc;
}
void L_Rote(AVLTree &tree)
{
PTNode rc;
rc = tree->right;
tree->right = rc->left;
rc->left = tree;
tree = rc;
}
int delete_key_from_AVL(AVLTree &tree, int key,int &lower)
{
PTNode p, q = NULL; // 删除结点~
int targ = 0; // 标志位,即删除左结点或右结点~
int return_flag = 0;
if(!tree)
{// 可能出现删除叶子为空的情况不?
return 0;
}
if(EQ(key, tree->key))
{// 如果为要删除结点,~
lower = TRUE; // 即找到所要删除结点,致标识为TRUE~
if(NULL==tree->right)
{ // 如果没有右节点
p = tree;
tree = tree->left;
free(p);
return 1; // 原tree左子树平衡,无需调整~
}
else
{
p = tree->right;
while(p->left != NULL)
{ // 找到tree的右子树的最左结点~
p = p->left;
}
tree->key = p->key;
return_flag = delete_key_from_AVL(tree->right, p->key, lower);
targ = RH;
}
}
else if(LT(key, tree->key))
{
return_flag = delete_key_from_AVL(tree->left, key, lower);
targ = LH;
}
else
{
return_flag = delete_key_from_AVL(tree->right, key, lower);
targ = RH;
}
// 保证存在过为key的结点~
if(TRUE == lower)
{
if(targ==LH)
{// 删除的是左子树
switch(tree->bf)
{
case LH: // 由于原来左右高度分别为h、h-1,现在左子树删除,则
tree->bf = EH; lower = TRUE; break;
case EH:
tree->bf = RH; lower = FALSE;break;
case RH: // 如果原右子树已比左子树高1~,现在又删左子树,将导致不平衡~
right_ballance(tree); lower=TRUE; break;
} // switch(tree->bf)
}
else
{// 删除的是右子树
switch(tree->bf)
{
case LH:
left_ballance(tree); lower = TRUE; break;
case EH:
tree->bf = LH; lower = FALSE; break;
case RH:
tree->bf = EH; lower = TRUE; break;
} // switch(tree->bf)
}
}// if(TRUE == lower)
return return_flag;
}
void vist_tree_in_first(const AVLTree tree)
{
if(NULL==tree)
return;
printf("%-4d", tree->key);
vist_tree_in_first(tree->left);
vist_tree_in_first(tree->right);
}
void destroy_tree(AVLTree tree)
{
if(!tree)
return;
destroy_tree(tree->left);
destroy_tree(tree->right);
free(tree);
tree = NULL;
}
int main()
{
AVLTree tree = NULL;
int keys[] = {10, 2, 11, 1, 4, 12,3};
int lower = FALSE;
insert_keys_to_AVL(tree, keys, 7);
vist_tree_in_first(tree);
printf("\n");
lower = FALSE;
delete_key_from_AVL(tree, 2, lower);
vist_tree_in_first(tree);
printf("\n");
destroy_tree(tree);
return 0;
}
运行截图: