我一直对平衡二叉树感兴趣,数据结构和算法妙趣横生,仔细体会,对编程莫大裨益。花了一个星期的业余时间,初步写完了AVL Tree,目前还在继续查找Bug中。
AVL树使用平衡因子来决定是否对树进行旋转。对树进行旋转有四种情况。但首先是某个平衡因子的值达到了2或者-2,再根据该节点的子节点的平衡因子是1还是-1,进行相应的旋转。
关于AVL的一些特性,可以参考国外教材《算法和数据结构 C语言描述》这本书。
#include <stdio.h>
#include <stdlib.h>
typedef struct AVLNode {
void *value;
struct AVLNode *parent;
struct AVLNode *lchild;
struct AVLNode *rchild;
int gap;
}AVLNode , *Node;
typedef struct AVLTree {
Node root;
int (*Compare) (void *value1 , void *value2);
}Tree , *AVLTree;
static Node Search (AVLTree avltr , void *value);
static Node NodeInitial (void *value);
static AVLTree TreeInitial (int (*Compare) (void *value1 , void *value2));
static void ReplaceNode (AVLTree avltr , Node node1 , Node node2);
static void Insert (AVLTree avltr , Node avlnode);
static void Delete (AVLTree avltr , Node avlnode);
static void AVLPrint (Node root);
static void FreeAVL (Node root);
static Node FindSubMax (Node avlnode);
static Node FindSubMin (Node avlnode);
static Node FindMax (AVLTree avltr);
static Node FindMin (AVLTree avltr);
static Node FindSuccessor (Node avlnode);
void LeftRotate (AVLTree avltr , Node avlnode);
void RightRotate (AVLTree avltr , Node avlnode);
void LeftRightRotate (AVLTree avltr , Node avlnode);
void RightLeftRotate (AVLTree avltr , Node avlnode);
void AVLInsertBalance (AVLTree avltr , Node avlnode);
void AVLDeleteBalance (AVLTree avltr , Node avlnode);
void LeftRotate (AVLTree avltr , Node avlnode) {
Node righttree = avlnode->rchild;
Node pa_node = avlnode->parent;
Node rlchild = righttree->lchild;
righttree->parent = pa_node;
if(pa_node == NULL) {
avltr->root = righttree;
} else if(pa_node->lchild == avlnode) {
pa_node->lchild = righttree;
} else {
pa_node->rchild = righttree;
}
avlnode->parent = righttree;
righttree->lchild = avlnode;
avlnode->rchild = rlchild;
if(rlchild != NULL) {
rlchild->parent = avlnode;
}
}
void RightRotate (AVLTree avltr , Node avlnode) {
Node lefttree = avlnode->lchild;
Node pa_node = avlnode->parent;
Node lrchild = lefttree->rchild;
lefttree->parent = pa_node;
if(pa_node == NULL) {
avltr->root = lefttree;
} else if(pa_node->lchild == avlnode) {
pa_node->lchild = lefttree;
} else {
pa_node->rchild = lefttree;
}
avlnode->parent = lefttree;
lefttree->rchild = avlnode;
avlnode->lchild = lrchild;
if(lrchild != NULL) {
lrchild->parent = avlnode;
}
}
void LeftRightRotate (AVLTree avltr , Node avlnode) {
LeftRotate(avltr , avlnode->rchild);
RightRotate(avltr , avlnode);
}
void RightLeftRotate (AVLTree avltr , Node avlnode) {
RightRotate(avltr , avlnode->lchild);
LeftRotate(avltr , avlnode);
}
int IntComp (void *value1 , void *value2) {
if (*(int *)value1 > *(int *)value2) return 1;
if (*(int *)value1 < *(int *)value2) return -1;
return 0;
}
static AVLTree TreeInitial (int (*Compare) (void *value1 , void *value2)) {
AVLTree tree = (AVLTree) malloc (sizeof (Tree));
printf ("Size of Tree is %d\n",sizeof(Tree));
tree->Compare = Compare;
tree->root = NULL;
return tree;
}
static Node NodeInitial (void *value) {
printf("Initial Node.\n");
Node avlnode = (Node) malloc (sizeof (AVLNode));
if (avlnode == NULL) printf("Initial Node with error.\n");
avlnode->gap = 0;
avlnode->lchild = NULL;
avlnode->parent = NULL;
avlnode->rchild = NULL;
avlnode->value = value;
printf ("Initilized Node value is %d.\n",*(int *)avlnode->value);
return avlnode;
}
static Node Search (AVLTree avltr , void *value) {
Node root = avltr->root;
while (root != NULL) {
if(avltr->Compare(root->value , value) == 0) {
return root;
} else if (avltr->Compare(root->value , value) < 0) {
root = root->rchild;
} else {
root = root->lchild;
}
}
return NULL;
}
static Node FindSubMax (Node avlnode) {
Node node = avlnode;
while (node->rchild != NULL) {
node = node->rchild;
}
return node;
}
static Node FindSubMin (Node avlnode) {
Node node = avlnode;
while (node->lchild !=NULL) {
node = node->lchild;
}
return node;
}
static Node FindMax (AVLTree avltr) {
Node node = avltr->root;
if(node == NULL) {
return NULL;
} else {
return FindSubMax(node);
}
}
static Node FindMin (AVLTree avltr) {
Node node = avltr->root;
if (node == NULL) {
return NULL;
} else {
return FindSubMin(node);
}
}
static Node FindSuccessor (Node avlnode) {
Node node = avlnode;
if (node->rchild != NULL) {
return FindSubMin (node->rchild);
} else {
Node pa = node->parent;
while ( pa != NULL && node == pa->rchild ) {
node = pa;
pa = pa->parent;
}
return pa;
}
}
static void ReplaceNode (AVLTree avltr , Node node1 , Node node2) {
if (avltr->Compare(node1->value , node2->value)!=0) {
return;
} else {
node1->value = node2->value;
}
}
static void Insert (AVLTree avltr , Node avlnode) {
if (avlnode == NULL) {
return;
}
if (avltr == NULL) {
return;
}
if (avltr->root == NULL) {
avltr->root = avlnode;
} else {
Node node = avltr->root;
Node pa_node = NULL;
while (node != NULL) {
pa_node = node;
if (avltr->Compare(node->value,avlnode->value) < 0) {
node = node->rchild;
} else if (avltr->Compare(node->value,avlnode->value) > 0) {
node = node->lchild;
} else {
ReplaceNode(avltr,node,avlnode);
return;
}
}
avlnode->parent = pa_node;
if(avltr->Compare(pa_node->value , avlnode->value) >0) {
pa_node->lchild = avlnode;
pa_node->gap++;
} else {
pa_node->rchild = avlnode;
pa_node->gap--;
}
AVLInsertBalance (avltr , pa_node);
}
}
static void Delete (AVLTree avltr , Node avlnode) {
if (avltr == NULL || avltr->root == NULL) return;
Node p_node = NULL , d_node = NULL , s_node = NULL;
if(avlnode->lchild != NULL && avlnode->rchild != NULL) {
d_node = FindSuccessor(avlnode);
} else {
d_node = avlnode;
}
p_node = d_node->parent;
if (d_node->rchild != NULL) {
s_node = d_node->rchild;
} else {
s_node = d_node->lchild;
}
if (p_node->lchild == d_node) {
p_node->lchild = s_node;
p_node->gap--;
} else {
p_node->rchild = s_node;
p_node->gap++;
}
if (s_node != NULL) {
s_node->parent = p_node;
}
if (d_node != avlnode) {
avlnode->value = d_node->value;
}
AVLDeleteBalance(avltr , p_node);
free(d_node);
}
void AVLInsertBalance (AVLTree avltr , Node avlnode) {
Node p_node = avlnode->parent;
Node node = avlnode;
while (p_node != NULL) {
if (p_node->lchild == node) {
p_node->gap++;
} else {
p_node->gap--;
}
if (p_node->gap == 0){
return;
}
else if (p_node->gap == 1 || p_node->gap == -1) {
node = p_node;
p_node = p_node->parent;
}
else if (p_node->gap > 1) {
if (node->gap == 1) {
p_node->gap-=2;
node->gap-=1;
RightRotate(avltr , p_node);
return;
}
if (node->gap == -1) {
p_node->gap-=2;
node->gap+=1;
LeftRightRotate(avltr , p_node);
return;
}
}
else {
if (node->gap == -1) {
p_node->gap+=2;
node->gap+=1;
LeftRotate(avltr , p_node);
return;
}
if (node->gap == 1) {
p_node->gap+=2;
node->gap-=1;
RightLeftRotate (avltr , p_node);
return;
}
}
}
}
void AVLDeleteBalance (AVLTree avltr , Node avlnode) {
Node node = avlnode;
Node pa_node = avlnode;
while (pa_node != NULL) {
node = pa_node;
if (node->gap == 2) {
Node lch_node = node->lchild;
if (lch_node->gap == 1) {
node->gap-=2;
lch_node->gap-=1;
RightRotate(avltr , node);
pa_node = lch_node->parent;
if (pa_node != NULL) {
if (pa_node->lchild == lch_node) {
pa_node->gap--;
} else {
pa_node->gap++;
}
}
}
if (lch_node->gap == -1) {
node->gap-=2;
lch_node->gap+=1;
LeftRightRotate(avltr , node);
Node new_root = lch_node->rchild;
pa_node = new_root->parent;
if (pa_node != NULL) {
if (pa_node->lchild == new_root) {
pa_node->gap--;
} else {
pa_node->gap++;
}
}
}
}
if (node->gap == -2) {
Node rch_node = node->rchild;
if (rch_node->gap == -1) {
node->gap+=2;
rch_node->gap+=1;
LeftRotate (avltr , node);
pa_node = rch_node->parent;
if (pa_node != NULL) {
if (pa_node->lchild == rch_node) {
pa_node->gap--;
} else {
pa_node->gap++;
}
}
}
if (rch_node->gap == 1) {
node->gap+=2;
rch_node->gap-=1;
RightLeftRotate (avltr , node);
Node new_root = rch_node->lchild;
pa_node = new_root->parent;
if (pa_node != NULL) {
if (pa_node->lchild == new_root) {
pa_node->gap--;
} else {
pa_node->gap++;
}
}
}
}
if (node->gap == 0) {
pa_node = node->parent;
if (pa_node != NULL) {
if (pa_node->lchild == node) {
pa_node->gap--;
} else {
pa_node->gap++;
}
}
}
if (node->gap == 1 || node->gap == -1) return;
}
}
static void AVLPrint (Node root) {
Node node = root;
if (node != NULL) {
AVLPrint (node->lchild);
printf("%d:%d ",*(int *)node->value,node->gap);
AVLPrint (node->rchild);
}
}
static void FreeAVL (Node root) {
Node node = root;
if (node != NULL) {
FreeAVL (node->lchild);
free(node);
FreeAVL (node->rchild);
}
}
void main (void) {
AVLTree avltr = TreeInitial (IntComp);
int a = 100;
Node node1 = NodeInitial (&a);
Insert (avltr , node1);
int b = 56;
Node node2 = NodeInitial (&b);
Insert (avltr , node2);
int c = 32;
Node node3 = NodeInitial (&c);
Insert (avltr , node3);
int d = 67;
Node node4 = NodeInitial (&d);
Insert (avltr , node4);
int e = 21;
Node node5 = NodeInitial (&e);
Insert (avltr , node5);
int f = 18;
Node node6 = NodeInitial (&f);
Insert (avltr , node6);
int g = 17;
Node node7 = NodeInitial (&g);
Insert (avltr , node7);
AVLPrint (avltr->root);
printf("\n");
Delete (avltr , node3);
AVLPrint (avltr->root);
}