AVL Operation
2013-01-05 16:09
162 查看
AVL本质是一棵二叉搜索树,为了改进二叉搜索树的效率,将其平衡化处理。所谓的AVL算法是又两名俄罗斯人在20世纪60年代提出,由他们的名字命名的。数据结构书上都会介绍这个算法,其原理比较直观,但是好像完整实现的源码不算多,此处补上一份。贴出的大部分源码来自由Mark Allen Weiss所著的由冯舜玺所译的《数据结构与算法分析——C语言描述》一书,删除算法(delete)则由我自己独立思考完成。
在linux下编译:
# gcc -DN=16 szlavltree.c main.c
# ./a.out
|-9
|-5
| |-3
| | |-2
| | | |-1
| | |-4
| |-7
| | |-6
| | |-8
|-13
| |-11
| | |-10
| | |-12
| |-15
| | |-14
| | |-16
Deletion: -1 means end of input
Delete X=9
Delete X=13
Delete X=7
Delete X=-1
|-8
|-3
| |-2
| | |-1
| |-5
| | |-4
| | |-6
|-14
| |-11
| | |-10
| | |-12
| |-15
| | |-16
Height=3, MAX=16, MIN=1
/* * szlavltree.h */ #ifndef Avl_Tree_H #define Avl_Tree_H #define ElementType int struct AvlNode; typedef struct AvlNode* Position; typedef struct AvlNode* AvlTree; void MakeEmpty(AvlTree T); Position Find(ElementType X, AvlTree T); Position FindMin(AvlTree T); Position FindMax(AvlTree T); AvlTree Insert(ElementType X, AvlTree T); AvlTree Delete(ElementType X, AvlTree T); ElementType Retrieve(Position P); void Print(AvlTree T); int TreeHeight(AvlTree T); #endif
/* * szlavltree.c */ #include "szlavltree.h" #include "stdio.h" #include <assert.h> #include <stdlib.h> #define Max(a,b) ((a)>(b)?(a):(b)) //the outermost paratheses are necessary static int Height(Position ); static Position SingleRotateWithLeft(Position ); static Position SingleRotateWithRight(Position ); static Position DoubleRotateWithLeft(Position ); static Position DoubleRotateWithRight(Position ); static void PrintA(AvlTree T, int layer); struct AvlNode{ ElementType Element; AvlTree Left; AvlTree Right; int Height; }; int TreeHeight(AvlTree T){ return Height(T); } AvlTree Insert(ElementType X, AvlTree T){ if(NULL == T){ T=(AvlTree)malloc(sizeof(struct AvlNode)); assert(NULL != T); T->Left=NULL; T->Right=NULL; T->Element=X; T->Height=0; return T; } else if(X<T->Element){ T->Left=Insert(X,T->Left); if(Height(T->Left)-Height(T->Right)==2){ if(X<T->Left->Element){ T=SingleRotateWithLeft(T); } else{ T=DoubleRotateWithLeft(T); } } } else if(X>T->Element){ T->Right=Insert(X,T->Right); if(Height(T->Right)-Height(T->Left)==2){ if(X>=T->Right->Element){ T=SingleRotateWithRight(T); } else{ T=DoubleRotateWithRight(T); } } } //else X is in the tree, we will do nothing. T->Height=Max(Height(T->Left),Height(T->Right))+1; return T; } static Position SingleRotateWithLeft(Position K2){ Position K1; K1=K2->Left; K2->Left=K1->Right; K1->Right=K2; K2->Height=Max(Height(K2->Left),Height(K2->Right))+1; K1->Height=Max(Height(K1->Left),K2->Height)+1; return K1; } static Position SingleRotateWithRight(Position K2){ Position K1; K1=K2->Right; K2->Right=K1->Left; K1->Left=K2; K2->Height=Max(Height(K2->Left),Height(K2->Right))+1; K1->Height=Max(Height(K1->Right),K2->Height)+1; return K1; } static Position DoubleRotateWithLeft(Position K3){ K3->Left=SingleRotateWithRight(K3->Left); return SingleRotateWithLeft(K3); } static Position DoubleRotateWithRight(Position K1){ K1->Right=SingleRotateWithLeft(K1->Right); return SingleRotateWithRight(K1); } static int Height(Position P){ if(NULL == P){ return -1; } else{ return P->Height; } } void MakeEmpty(AvlTree T){ if(NULL!=T){ AvlTree left=T->Left; AvlTree right=T->Right; free(T); MakeEmpty(left); MakeEmpty(right); } } Position Find(ElementType X, AvlTree T){ if(NULL==T){ return NULL; } if(X==T->Element){ return T; } else if(X<T->Element){ return Find(X,T->Left); } else{ return Find(X,T->Right); } } Position FindMin(AvlTree T){ if(NULL==T){ return NULL; } else if(NULL==T->Left){ return T; } else{ return FindMin(T->Left); } } Position FindMax(AvlTree T){ if(NULL==T){ return NULL; } else if(NULL==T->Right){ return T; } else{ return FindMax(T->Right); } } AvlTree Delete(ElementType X, AvlTree T){ if(NULL==T){ return NULL; } else{ if(X==T->Element){//if the current node is what we want to delete if(Height(T->Left)>Height(T->Right)){//delete from the subtree with larger Height, this would help protect the tree is still AVL tree. Position leftMax=FindMax(T->Left); T->Element=leftMax->Element; leftMax->Element=X; T->Left=Delete(X,T->Left); } else if(Height(T->Left)<Height(T->Right)){ Position rightMin=FindMin(T->Right); T->Element=rightMin->Element; rightMin->Element=X; T->Right=Delete(X,T->Right); } else{ //Height(T->Left == Height(T->Right) if(NULL!=T->Left){//NULL!=T->Left && NULL!=T->Right Position rightMin=FindMin(T->Right); T->Element=rightMin->Element; rightMin->Element=X; T->Right=Delete(X,T->Right); } else{//NULL==T->Left && NULL == T->Right free(T); T=NULL; } } }// the deletion of current node promise that after the operation the tree is still an AVL tree. else{//X!=T->Element if(X<T->Element){//delete from the left sub tree, which could lead to the root tree node unbalanced. So we need to rotate it to // guarantee it is an AVL tree. T->Left=Delete(X,T->Left); if(2==Height(T->Right)-Height(T->Left)){ T=SingleRotateWithRight(T); } } else{//X>T->Element, delete from the right sub tree T->Right=Delete(X,T->Right); if(2==Height(T->Left)-Height(T->Right)){ T=SingleRotateWithLeft(T); } } } //adjust the Height of the tree if(NULL!=T){ T->Height=Max(Height(T->Left),Height(T->Right))+1; } return T; } } ElementType Retrieve(Position P){ assert(NULL!=P); return P->Element; } void Print(AvlTree T){ PrintA(T,0); } static void PrintA(AvlTree T, int layer){ int l=layer; if(NULL==T){ #ifdef MODE1 printf("%s:%d\n",__FUNCTION__, __LINE__); #endif return; } while(l!=0){ printf(" "); if(1<l){ printf("|"); } l--; } printf("|-%d\n",(int)(T->Element)); if(NULL!=T->Left){ PrintA(T->Left,layer+1); } if(NULL!=T->Right){ PrintA(T->Right,layer+1); } }
/* * main.c */ #include "szlavltree.h" #include <stdio.h> #define MAX (10) main(){ int i=0; int a; int n=MAX; #ifdef N n=N; #endif AvlTree T=NULL; for(;i<n;i++){ //scanf("%d",&a); a=n-i; T=Insert(a,T); } if(NULL==T){ puts("Build failed."); } Print(T); puts("Deletion: -1 means end of input"); while(1){ printf("Delete X="); scanf("%d",&a); if(-1!=a){ Delete(a,T); } else{ break; } } Print(T); printf("Height=%d, MAX=%d, MIN=%d\n",TreeHeight(T),Retrieve(FindMax(T)),Retrieve(FindMin(T))); MakeEmpty(T); }
在linux下编译:
# gcc -DN=16 szlavltree.c main.c
# ./a.out
|-9
|-5
| |-3
| | |-2
| | | |-1
| | |-4
| |-7
| | |-6
| | |-8
|-13
| |-11
| | |-10
| | |-12
| |-15
| | |-14
| | |-16
Deletion: -1 means end of input
Delete X=9
Delete X=13
Delete X=7
Delete X=-1
|-8
|-3
| |-2
| | |-1
| |-5
| | |-4
| | |-6
|-14
| |-11
| | |-10
| | |-12
| |-15
| | |-16
Height=3, MAX=16, MIN=1