平衡二叉树
1、定义:AVL(平衡二叉树)是带有平衡条件的二叉查找树。
2、性质:
(1)平衡二叉树的深度是O(logN)
(2)平衡二叉树是有平衡条件的二叉树,所以在搜索二叉树的基础上加上平衡二叉树的高度。
(3)在高度为h的平衡二叉树中,最少节点数S(h)=S(h-1)+S(h-2)+1
S(0)=1,S(1)=2;
(4)搜索二叉树的所有性质,平衡二叉树都满足。
3、代码实现思路:
(1)平衡二叉树的结构体中除了搜索二叉树的结构外,还要有高度,用来判断平衡二叉树是否平衡。
(2)平衡二叉树的主要操作有旋转,插入,删除,求高度4种
(3)平衡二叉树的旋转是当平衡二叉树的平衡条件被打破的时候要做的操作。
旋转分为四种:
1、对左子树的左子树进行旋转(单左旋)
2、对右子树的右子树进行旋转(单右旋)
3、对左子树的右子树进行旋转(左-右双旋)
4、对右子树的左子树进行旋转(右-左双旋)
1,2和3,4为镜像操作
1、单左旋:当节点的左子树的高度比右子树的高度大二时,此节点的平衡被打破,即左边的平衡被破坏,所以是单左旋
调整过程:
(1)记录此节点k2,k2的左子节点k1
(2)令k1的右儿子变为k2的左儿子
(3)k1的右儿子变为k2
(4)更新k1的高度
(5)更新k2的高度
2、单右旋:同理1
3、左-右双旋
调整过程:
(1)k3是根节点,k1是k3的左结点,k2是k1的右节点
(2)先对k1进行单右旋,再对k3进行单左旋(从底向上,先右后左(右指对左子树进行右旋,左指对原节点进行左旋))。
4、右-左双旋:同理3
(补充:
(1)这个调整过程一定是正确的,因为由搜索二叉树的性质(根节点的值大于所有根节点的左子树的值,根节点的值小于所有根节点的右子树的值)
(2)双旋相当于两次单旋转调整,需要从底向上逐层调整
(3)判断节点需要怎么调整只看节点的底下两层就行了。
)
(4)插入
插入操作分三种情况:
1、如果是空,就表示找到位置,插入即可
2、如果x小于当前节点的值就向左子树插入
比较插入后此节点是否仍然保持平衡,如果不平衡,就进行调整
比较此节点的下一层的节点与当前节点的值的大小,并进行单旋转或者双旋转的调整。
3、如果x大于当前节点的值就向右子树插入
比较插入后此节点是否仍然保持平衡,如果不平衡,就进行调整
比较此节点的下一层的节点与当前节点的值的大小,并进行单旋转或者双旋转的调整。
(补充:注意最后调整节点的高度,节点的高度是最大左子树或者右子树的高度+1)
(4)删除
删除分5种操作
1、T为空,直接返回空
2、节点的值小于x,对此节点的左子树进行删除
删除结束后判断此节点的平衡是否被打破,进行适当的调整
3、节点的值大于x,对此节点的右子树进行删除
删除结束后判断此节点是否平衡,进行适当的调整
4、节点的值等于x,有三种情况
如果是叶子节点,直接删除
如果是只有一个孩子的节点,直接指向它的孩子
如果是有有两个孩子的节点,有两种情况
一、左子树的高度高于右子树的高度,选择左子树的最大值,替换此节点的值,然后删除左子树的最大值
二、左子树的高度低于右子树的高度,选择右子树的最小值,替换此节点的值,然后删除右子树的最小值
(正确性:因为高度最高的树中的最小值(或者最大值最接近要此节点的值,所以替换后的变动会小一些))。
#include<stdio.h> #include<stdlib.h> struct Node{ int data,Height; struct Node *Left,*Right; }; typedef struct Node* AVL; typedef AVL Position; int MAX(int x,int y) { return x>y?x:y; } void MakeEmpty(AVL T) { if(T!=NULL) { MakeEmpty(T->Left); MakeEmpty(T->Right); free(T); } } int Height(AVL T) { if(T==NULL) return -1; else return T->Height; } AVL SingleLeftRotate(AVL T) { AVL p=T->Left; T->Left=p->Right; p->Right=T; T->Height=MAX(Height(T->Left),Height(T->Right))+1; p->Height=MAX(Height(p->Left),T->Height)+1; return p; } AVL SingleRightRotate(AVL T) { AVL p=T->Right; T->Right=p->Left; p->Left=T; T->Height=MAX(Height(T->Left),Height(T->Right))+1; p->Height=MAX(Height(p->Right),T->Height)+1; return p; } AVL DoubleLeftRightRotate(AVL T) { T->Left=SingleRightRotate(T->Left); return SingleLeftRotate(T); } AVL DoubleRightLeftRotate(AVL T) { T->Right=SingleLeftRotate(T->Right); return SingleRightRotate(T); } AVL Insert(int x,AVL T) { if(T==NULL) { T=(AVL)malloc(sizeof(struct Node)); if(T==NULL) printf("Out of Space!!!\n"); else { T->data=x; T->Height=0; T->Left=NULL; T->Right=NULL; } } else if(x<T->data) { T->Left=Insert(x,T->Left); if(Height(T->Left)-Height(T->Right)==2) { if(x<T->Left->data) T=SingleLeftRotate(T); else T=DoubleLeftRightRotate(T); } } else { T->Right=Insert(x,T->Right); if(Height(T->Left)-Height(T->Right)==-2) { if(x>T->Right->data) T=SingleRightRotate(T); else T=DoubleRightLeftRotate(T); } } T->Height=MAX(Height(T->Left),Height(T->Right))+1; return T; } Position Find(int x,AVL T) { if(T==NULL) return NULL; else if(x<T->data) return Find(x,T->Left); else if(x>T->data) return Find(x,T->Right); return T; } Position FindMin(AVL T) { if(T==NULL) return NULL; else if(T->Left!=NULL) return FindMin(T->Left); else return T; } Position FindMax(AVL T) { if(T==NULL) return NULL; else if(T->Right!=NULL) return FindMax(T->Right); else return T; } AVL DeleteAVL(int x,AVL T) { AVL tp; if(T==NULL) { printf("Error");return NULL; } else if(x<T->data) { T->Left=DeleteAVL(x,T->Left); if(Height(T->Left)-Height(T->Right)==2) { tp=T->Left; if(Height(tp->Left)>Height(tp->Right)) T=SingleLeftRotate(T); else T=DoubleLeftRightRotate(T); } } else if(x>T->data) { T->Right=DeleteAVL(x,T->Right); if(Height(T->Left)-Height(T->Right)==-2) { tp=T->Right; if(Height(tp->Right)>Height(tp->Left)) T=SingleRightRotate(T); else T=DoubleRightLeftRotate(T); } } else { if(T->Left&&T->Right) { if(Height(T->Left)>=Height(T->Right)) { tp=FindMax(T->Left); T->data=tp->data; T->Left=DeleteAVL(T->data,T->Left); } else { tp=FindMin(T->Right); T->data=tp->data; T->Right=DeleteAVL(T->data,T->Right); } } else { tp=T; if(T->Left==NULL) T=T->Right; else if(T->Right==NULL) T=T->Left; free(tp); } } if(T!=NULL) T->Height=MAX(Height(T->Left),Height(T->Right))+1; return T; } struct N1{ AVL data; struct N1 *next; }; struct N2{ struct N1 *pre; struct N1 *rear; }; typedef struct N2* Queue; Queue CreateQueue() { Queue Q=(Queue)malloc(sizeof(struct N2)); if(Q==NULL) printf("Out of Space!!!\n"); Q->rear=(struct N1*)malloc(sizeof(struct N1)); Q->rear->next=NULL; Q->pre=Q->rear; return Q; } int IsEmpty(Queue Q) { return Q->pre==Q->rear; } void Push(AVL x,Queue Q) { struct N1* tp=(struct N1*)malloc(sizeof(struct N1)); tp->data=x; tp->next=Q->rear->next; Q->rear->next=tp; Q->rear=Q->rear->next; } AVL Top(Queue Q) { return Q->pre->next->data; } void Pop(Queue Q) { struct N1* tp=Q->pre->next; Q->pre->next=tp->next; free(tp); if(Q->rear==tp) Q->rear=Q->pre; } void Printpre(AVL T) { if(T!=NULL) { Printpre(T->Left); printf("%d ",T->data); Printpre(T->Right); } return ; } void Print(AVL T) { Queue Q=CreateQueue(); Push(T,Q); while(!IsEmpty(Q)) { AVL t=Top(Q); printf("%d ",t->data); Pop(Q); if(t->Left!=NULL) Push(t->Left,Q); if(t->Right!=NULL) Push(t->Right,Q); } printf("\n"); } int main(void) { int n,i,x; AVL T=NULL; scanf("%d",&n); for(i=0;i<n;i++) { scanf("%d",&x); T=Insert(x,T); } Print(T); T=DeleteAVL(8,T); Print(T); return 0; }