AVL树
动态平衡技术
Adelson-Velskii 和 Landis 提出了一个动态地保持二叉排序树平衡的方法,其基本思想是:
在构造二叉排序树的过程中,每当插入一个结点时,首先检查是否因插入而破坏了树的平衡性,如果是因插入结点而破坏了树的平衡性,则找出其中最小不平衡子树,在保持排序树特性的前提下,调整最小不平衡子树中各结点之间的连接关系,以达到新的平衡。通常将这样得到的平衡二叉排序树简称为 AVL 树。
那么什么是 最小不平衡子树
以离插入结点最近、且平衡因子绝对值大于 1 的结点作根结点的子树。为了简化讨论,不妨假设二叉排序树的最小不平衡子树的根结点为 A ,则调整该子树的规律可归纳为下列四种情况:
如图:当插入结点为53时,结点37则为最小不平衡子树 A
单向
(1) LL 型:(单向右旋)
原因是:在A的左子树插入左子树,导致A平衡恩子为2,失去平衡。需要向右旋转一次、
新结点 X 插在 A 的左孩子的左子树里。调整方法见图 8.5(a) 。图中以 B 为轴心,将 A 结点从 B 的右上方转到 B 的右下侧,使 A 成为 B 的右孩子。
(2)RR 型:(单向向左旋)
同上。则是方向变了右
新结点 X 插在 A 的右孩子的右子树里。调整方法见图 8.5(b) 。图中以 B 为轴心,将 A 结点从 B 的左上方转到 B 的左下侧,使 A 成为 B 的左孩子。
双向:
(3)LR 型:(先左后右)
新结点 X 插在 A 的左孩子的右子树里。调整方法见图 8.5(c) 。分为两步进行:第一步以 X 为轴心,将 B 从 X 的左上方转到 X 的左下侧,使 B 成为 X 的左孩子, X 成为 A 的左孩子。第二步跟 LL 型一样处理 ( 应以 X 为轴心 ) 。
//此时大小是 B<X<A 那么应该将中间的那个X做根结点
(4)RL 型:(先右后左)
新结点 X 插在 A 的右孩子的左子树里。调整方法见图 8.5(d) 。分为两步进行:第一步以 X 为轴心,将 B 从 X 的右上方转到 X 的右下侧,使 B 成为 X 的右孩子, X 成为 A 的右孩子。第二步跟 RR 型一样处理 ( 应以 X 为轴心
#include <stdio.h> #include <string.h> #include <stdlib.h> typedef int ELementType; struct AvlNode; typedef struct AvlNode *Position; typedef struct AvlNode *AvlTree; AvlTree 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); static int height(Position P); //旋转 static Position SingleRotateWithRight(Position K1); static Position SingleRotateWithLeft(Position K2); static Position DoubleRotateWithLeft(Position K3); static Position DoubleRotateWithRight(Position K4); ELementType Max( ELementType a, ELementType b); void PrintElement(AvlTree T); void PreOrder(AvlTree T); void InOrder(AvlTree T); void PostOrder(AvlTree T); struct AvlNode { ELementType ELement; AvlTree Left; AvlTree Right; int height; //节点对应高度 }; ELementType Max(ELementType a, ELementType b) { return (a > b ? a : b); } static int height(Position P) { if( P == NULL) return -1; else return P->height; } 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->ELement) return Find(X,T->Left ); else if( X > T->ELement) return Find(X,T->Right); else return T; } Position FindMin(AvlTree T) { if( T == NULL) return NULL; 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); } AvlTree Delete(ELementType X, AvlTree T) { return T; } AvlTree Insert( ELementType X, AvlTree T) { if( T == NULL) { T = malloc(sizeof(struct AvlNode)); if( T == NULL) printf("ERROR 129\n"); else { T->ELement = X; T->Left = T->Right = NULL; } } 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); } } } 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),height(K1->Right)) + 1; return K1; } static Position SingleRotateWithRight(Position K1) { Position K2; K2 = K1->Right; K1->Right = K2->Left; K2->Left = K1; K2->height = Max(height(K2->Left),height(K2->Right)) + 1; K1->height = Max(height(K1->Left),height(K1->Right)) + 1; return K2; } static Position DoubleRotateWithLeft(Position K3) { K3->Left = SingleRotateWithRight(K3->Left); return SingleRotateWithLeft(K3); } static Position DoubleRotateWithRight(Position K4) { K4->Right = SingleRotateWithLeft(K4->Right); return SingleRotateWithRight(K4); } ELementType Retrieve(Position P) { return P->ELement; } void PrintElement(AvlTree T) { printf("%3d ",Retrieve( T )); } void PreOrder( AvlTree T) { if( T != NULL) { PrintElement( T); PreOrder( T->Left); PreOrder( T->Right); } } void InOrder( AvlTree T) { if( T != NULL) { InOrder( T->Left); PrintElement( T); InOrder( T->Right); } } void PostOrder(AvlTree T ) { if( T != NULL) { PostOrder( T); PostOrder(T); PrintElement(T); } } int main() { AvlTree T = NULL; int i, n; int tmp; printf( "Number of Elements:" ); scanf( "%d", &n ); for ( i = 0; i < n; i++) { scanf( "%d", &tmp ); T = Insert( tmp, T ); } printf( "\nPreOrder :" ); PreOrder( T ); printf( "\nInOrder :" ); InOrder( T ); printf( "\nPostOrder:" ); PostOrder( T ); printf( "\n" ); return 0; }