所有原创文章转载请注明作者及链接
// blackboycpp(AT)gmail.com
// QQ群: 135202158
/******************************************************************** File: AVLTree.h Author: blackboy [email protected] Purpose: AVL树(一种带平衡条件的二叉查找树),C实现。不考虑重复元素。 Created: 2011-04-12 Modified: 2011-04-13 10:55 *********************************************************************/ #ifndef __AVL_TREE_H__ #define __AVL_TREE_H__ typedef int ElementType; struct _AVLNode; typedef struct _AVLNode AVLNode; typedef AVLNode* Position; typedef AVLNode* AVLTree; struct _AVLNode { ElementType Val; AVLTree Left; AVLTree Right; int Height; }; ////////////////////////////////////////////////////////////////////////// AVLTree MakeEmpty(AVLTree); Position Find(ElementType, AVLTree); Position FindMin(AVLTree); Position FindMax(AVLTree); AVLTree Insert(ElementType, AVLTree); AVLTree Delete(ElementType, AVLTree); AVLTree Delete2(ElementType, AVLTree); ElementType GetAt(Position); void InOrder(AVLTree); // 中序遍历 #endif
#include <stdlib.h> #include <stdio.h> #include "AVLTree.h" static int Height(Position P) { if(P == NULL) return -1; else return P->Height; } // 右旋转 - 在P与它的左子树Q之间实施旋转,将左边的某树移到右边,如图,将Y移到右边: /* P Q / / / / Q z ===> x P / / / / x y y z */ static Position SingleRotateWithLeft(Position P) { Position Q = P->Left; P->Left = Q->Right; Q->Right = P; P->Height = max(Height(P->Left), Height(P->Right)) + 1; Q->Height = max(Height(Q->Left), P->Height) + 1; return Q; // 返回新的root } // 左旋转, 与右旋转正好相反 static Position SingleRotateWithRight(Position P) { Position Q = P->Right; P->Right = Q->Left; Q->Left = P; P->Height = max(Height(P->Left), Height(P->Right)) + 1; Q->Height = max(P->Height, Height(Q->Right)) + 1; return Q; } // 左-右双旋转 /* P P Y / / / / / / X d X,Y右旋转 Y d P,Y左旋转 X P / / ==========> / / ==========> / / / / a Y X c a b c d / / / / b c a b */ static Position DoubleRotateWithLeft(Position P) { P->Left = SingleRotateWithRight(P->Left); return SingleRotateWithLeft(P); } // 右-左双旋转 static Position DoubleRotateWithRight(Position P) { P->Right = SingleRotateWithLeft(P->Right); return SingleRotateWithRight(P); } // 搜索并删除右子树中最小的节点。 // D: 要删除的节点;T:递归用的树,初始值为D的右子树。 // 注意:此函数被调用时,D必有左、右两个儿子。 static AVLTree DeleteRightMin(AVLTree D, AVLTree T) { Position Temp; // 最小节点必定没有左儿子 if(T->Left == NULL) { Temp = T; D->Val = T->Val; T = T->Right; free(Temp); } else T->Left = DeleteRightMin(D, T->Left); // 很关键,且容易出错 return T; } // 对于单个节点进行的AVL调整,用于Delete()函数。Delete2()不用它。 static AVLTree Rotate(AVLTree T) { if(Height(T->Left) - Height(T->Right) == 2) { if(Height(T->Left->Left) >= Height(T->Left->Right)) T = SingleRotateWithLeft(T); else T = DoubleRotateWithLeft(T); } if(Height(T->Right) - Height(T->Left) ==2) { if(Height(T->Right->Right) >= Height(T->Right->Left)) T = SingleRotateWithRight(T); else T = DoubleRotateWithRight(T); } return T; } ////////////////////////////////////////////////////////////////////////// // MakeEmpty()与Find()系列函数都与普通二叉查找树相同。 AVLTree MakeEmpty(AVLTree T) { if(T != NULL) { MakeEmpty(T->Left); MakeEmpty(T->Right); free(T); } return NULL; } Position Find(ElementType X, AVLTree T) { if(T == NULL) return NULL; if(X < T->Val) return Find(X, T->Left); else if(X > T->Val) return Find(X, T->Right); else // 递归终止条件 return T; } Position FindMin(AVLTree T) { if(T == NULL) return NULL; else if(T->Left == NULL) return T; else return FindMin(T->Left); } Position FindMax(AVLTree T) { if(T == NULL) return NULL; else if(T->Right == NULL) return T; else return FindMax(T->Right); // 非递归实现 /* if(T != NULL) { while(T->Right != NULL) { T = T->Right; } } return T; */ } ////////////////////////////////////////////////////////////////////////// AVLTree Insert(ElementType X, AVLTree T) { if(T == NULL) { T = (AVLTree)malloc(sizeof(AVLNode)); T->Left = T->Right = NULL; T->Height = 0; T->Val = X; } else if(X < T->Val) { T->Left = Insert(X, T->Left); if(Height(T->Left) - Height(T->Right) == 2) { if(X < T->Left->Val) T = SingleRotateWithLeft(T); else T = DoubleRotateWithLeft(T); } } else if(X > T->Val) { T->Right = Insert(X, T->Right); if(Height(T->Right) - Height(T->Left) == 2) { if(X > T->Right->Val) T = SingleRotateWithRight(T); else T = DoubleRotateWithRight(T); } } T->Height = max(Height(T->Left), Height(T->Right)) + 1; return T; } AVLTree Delete(ElementType X, AVLTree T) { Position Temp; if(T == NULL) // 空树 return NULL; else if(X < T->Val) T->Left = Delete(X, T->Left); else if(X > T->Val) T->Right = Delete(X, T->Right); else if(T->Left && T->Right) // 两个儿子 { T->Right = DeleteRightMin(T, T->Right); // 也可以如下实现,但效率较低,因为遍历了两遍右子树 /* Temp = FindMin(T->Right); T->Val = Temp->Val; T->Right = Delete(T->Val, T->Right); */ } else // 单个儿子 { Temp = T; if(T->Left == NULL) T = T->Right; else if(T->Right == NULL) T = T->Left; free(Temp); } if(T != NULL) { T->Height = max(Height(T->Left), Height(T->Right)) + 1; // 删除后,递归调用至根节点,并修复沿途每个节点的平衡性。 if(T->Left != NULL) T->Left = Rotate(T->Left); if(T->Right != NULL) T->Right = Rotate(T->Right); T = Rotate(T); } return T; } // 删除算法的第2种写法,虽然代码比上面的稍长,但我更喜欢这一种。 AVLTree Delete2( ElementType X, AVLTree T ) { Position Temp; if (T == NULL) return NULL; else if (X < T->Val) // 从左子树删除,右子树可能过高 { T->Left = Delete2( X, T->Left ); /* 图示:在P的左子树删除 (A) P的右子树的左子树高于P的右子树的右子树, 对P执行右-左双旋转 P P Y / 先右旋 / 再左旋 / / X ======> Y =======> P X / / Y X (B) P的右子树的右子树高于P的右子树的左子树,对P进行左旋转 P X / 左单旋转 / / X =========> P Y / Y */ if (Height(T->Right) - Height(T->Left) == 2) { if (Height(T->Right->Left) > Height(T->Right->Right)) T = DoubleRotateWithRight(T); else T = SingleRotateWithRight(T); } } else if (X > T->Val) // 从右子树删除,左子树可能过高 { T->Right = Delete2(X, T->Right); if (Height(T->Left) - Height(T->Right) == 2 ) { if (Height(T->Left->Right) > Height(T->Left->Left)) T = DoubleRotateWithLeft(T); else T = SingleRotateWithLeft(T); } } else if(T->Left && T->Right) { T->Right = DeleteRightMin(T, T->Right); // 找到右子树的最小节点,以其值替换当前值,并删除之。 if ( Height( T->Left ) - Height( T->Right ) == 2 ) { if (Height(T->Left->Right) > Height(T->Left->Left)) T = DoubleRotateWithLeft(T); else T = SingleRotateWithLeft(T); } } else { Temp = T; if (T->Left == NULL) T = T->Right; else if (T->Right == NULL) T = T->Left; free(Temp); } if(T != NULL) T->Height = max(Height(T->Left), Height(T->Right)) + 1; return T; } ElementType GetAt(Position P) { if(P == NULL) return -1; // 节点不存在 return P->Val; } void InOrder(AVLTree T) // 中序遍历 { if(T == NULL) return; InOrder(T->Left); printf("%d(%d) ", T->Val, T->Height); InOrder(T->Right); }
#include <stdio.h> #include <stdlib.h> #include "AVLTree.h" #define DEL_METHOD2 int main() { AVLTree Tree = NULL; Position Pos = NULL; Tree = Insert(5, Tree); /* 5 */ Tree = Insert(2, Tree); /* 5 / 2 */ Tree = Insert(8, Tree); /* 5 / / 2 8 */ Tree = Insert(1, Tree); /* 5 / / 2 8 / 1 */ Tree = Insert(3, Tree); /* 5 / / 2 8 / / 1 3 */ Tree = Insert(6, Tree); /* 5 / / 2 8 / / / 1 3 6 */ Tree = Insert(4, Tree); /* 5 / / 2 8 / / / 1 3 6 / 4 */ InOrder(Tree); printf("/n"); #ifndef DEL_METHOD2 Tree = Delete(3, Tree); #else Tree = Delete2(3, Tree); #endif InOrder(Tree); printf("/n"); Tree = Insert(3, Tree); InOrder(Tree); printf("/n"); /* 5 / / 2 8 / / / 1 4 6 / 3 */ #ifndef DEL_METHOD2 Tree = Delete(1, Tree); #else Tree = Delete2(1, Tree); #endif InOrder(Tree); printf("/n"); /* 5 / / 3 8 / / / 2 4 6 */ Tree = Insert(1, Tree); /* 5 / / 3 8 / / / 2 4 6 / 1 */ #ifndef DEL_METHOD2 Tree = Delete(6, Tree); #else Tree = Delete2(6, Tree); #endif InOrder(Tree); printf("/n"); /* 3 / / 2 5 / / / 1 4 8 */ Pos = Find(5, Tree); printf("Find: %d/n", GetAt(Pos)); Pos = FindMin(Tree); printf("Find: %d/n", GetAt(Pos)); Pos = FindMax(Tree); printf("Find: %d/n", GetAt(Pos)); Tree = MakeEmpty(Tree); system("PAUSE"); return 0; }