平衡二叉树
来源:互联网 发布:做自己想做的梦 知乎 编辑:程序博客网 时间:2024/05/01 13:20
平衡二叉树又称AVL树。它或者是颗空树,或者是具有下列性质的二叉树:它的左子树和右子树都是平衡二叉树,且左子树和右子树的深度之差的绝对值不超过1。若将二叉树节点的平衡因子BF定义为该节点的左子树的深度减去它的右子树的深度,则平衡二叉树上所有节点的平衡因子只可能为-1,0,1.只要二叉树上有一个节点的平衡因子的绝对值大于1,那么这颗平衡二叉树就失去了平衡。
假设我们已经有棵平衡二叉树,现在让我们来看看插入节点后,原来节点失去平衡后,我们进行选择的处理方式。
平衡二叉树多用于查找数据,所以平衡二叉树又是颗二叉排序树。
那么如何创建一颗平衡二叉树呢?
创建平衡二叉树,我们采用依次插入节点的方式进行。而平衡二叉树上插入节点采用递归的方式进行。递归算法如下:
(1) 若该树为一空树,那么插入一个数据元素为e的新节点作为平衡二叉树的根节点,树的高度增加1。
(2) 若待插入的数据元素e和平衡二叉树(BBST)的根节点的关键字相等,那么就不需要进行插入操作。
(3) 若待插入的元素e比平衡二叉树(BBST)的根节点的关键字小,而且在BBST的左子树中也不存在和e有相同关键字的节点,则将e插入在BBST的左子树上,并且当插入之后的左子树深度增加1时,分别就下列情况处理之。
(a) BBST的根节点的平衡因子为-1(右子树的深度大于左子树的深度):则将根节点的平衡因子更改为0,BBST的深度不变;
(b) BBST的根节点的平衡因子为0(左右子树的深度相等):则将根节点的平衡因子修改为1,BBST的深度增加1;
(c) BBST的根节点的平衡因子为1(左子树的深度大于右子树的深度):若BBST的左子树根节点的平衡因子为1,则需要进行单向右旋转平衡处理,并且在右旋处理后,将根节点和其右子树根节点的平衡因子更改为0,树的深度不变;
若BBST的左子树根节点的平衡因子为-1,则需进行先向左,后向右的双向旋转平衡处理,并且在旋转处理之后,修改根节点和其左,右子树根节点的平衡因子,树的深度不变;
(4) 若e的关键字大于BBST的根节点的关键字,而且在BBST的右子树中不存在和e有相同关键字的节点,则将e插入到BBST的右子树上,并且当插入之后的右子树深度加1时,分别就不同的情况处理之。
(a) BBST的根节点的平衡因子是1(左子树的深度大于右子树的深度):则将根节点的平衡因子修改为0,BBST的深度不变;
(b) BBST的根节点的平衡因子是0(左右子树的深度相等):则将根节点的平衡因子修改为-1,树的深度加1;
(c) BBST的根节点的平衡因子为-1(右子树的深度大于左子树的深度):若BBST的右子树根节点的平衡因子为1,则需要进行两次选择,第一次先向右旋转,再向左旋转处理,并且在旋转处理之后,修改根节点和其左,右子树根节点的平衡因子,树的深度不变;
若BBST的右子树根节点的平衡因子为1,则需要进行一次向左的旋转处理,并且在左旋之后,更新根节点和其左,右子树根节点的平衡因子,树的深度不变;
/*首先平衡二叉树是一个二叉排序树;其基本思想是:在构建二叉排序树的过程中,当每插入一个节点时,先检查是否因为插入而破坏了树的平衡性,若是,找出最小不平衡树,进行适应的旋转,使之成为新的平衡二叉树。*/#include<stdio.h>#include<stdlib.h>#define LH 1#define EH 0#define RH -1typedef struct BTNode{ int data; int BF;//平衡因子(balance factor) struct BTNode *lchild,*rchild;}BTNode,*BTree;void R_Rotate(BTree *p)//以p为根节点的二叉排序树进行右旋转{ BTree L; L=(*p)->lchild; (*p)->lchild=L->rchild; L->rchild=(*p); *p=L;//p指向新的根节点}void L_Rotate(BTree *p)//以p为根节点的二叉排序树进行左旋转{ BTree R; R=(*p)->rchild; (*p)->rchild=R->lchild; R->lchild=(*p); *p=R;}void LeftBalance(BTree *T){ BTree L,Lr; L=(*T)->lchild; switch(L->BF) { //检查T的左子树平衡度,并作相应的平衡处理 case LH://新节点插入在T的左孩子的左子树上,做单右旋处理 (*T)->BF=L->BF=EH; R_Rotate(T); break; case RH://新插入节点在T的左孩子的右子树上,做双旋处理 Lr=L->rchild; switch(Lr->BF) { case LH: (*T)->BF=RH; L->BF=EH; break; case EH: (*T)->BF=L->BF=EH; break; case RH: (*T)->BF=EH; L->BF=LH; break; } Lr->BF=EH; L_Rotate(&(*T)->lchild); R_Rotate(T); }}void RightBalance(BTree *T){ BTree R,Rl; R=(*T)->rchild; switch(R->BF) { case RH://新节点插在T的右孩子的右子树上,要做单左旋处理 (*T)->BF=R->BF=EH; L_Rotate(T); break; case LH://新节点插在T的右孩子的左子树上,要做双旋处理 Rl=R->lchild; switch(Rl->BF) { case LH: (*T)->BF=EH; R->BF=RH; break; case EH: (*T)->BF=R->BF=EH; break; case RH: (*T)->BF=LH; R->BF=EH; break; } Rl->BF=EH; R_Rotate(&(*T)->rchild); L_Rotate(T); }}int InsertAVL(BTree *T,int e,int *taller)//变量taller反应T长高与否{ if(!*T) { *T=(BTree)malloc(sizeof(BTNode)); (*T)->data=e; (*T)->lchild=(*T)->rchild=NULL; (*T)->BF=EH; *taller=1; } else { if(e==(*T)->data)//不插入 { *taller=0; return 0; } if(e<(*T)->data) { if(!InsertAVL(&(*T)->lchild,e,taller))//未插入 return 0; if(*taller)//以插入左子树,且左子树变高 { switch((*T)->BF) { case LH://原本左子树比右子树高,需要做左平衡处理 LeftBalance(T); *taller=0; break; case EH://原本左右子树等高,现因左子树增高而树增高 (*T)->BF=LH; *taller=1; break; case RH://原本右子树比左子树高,现在左右子树等高 (*T)->BF=EH; *taller=0; break; } } } else { //应在T的右子树中搜寻 if(!InsertAVL(&(*T)->rchild,e,taller)) return 0; if(*taller)//插入右子树,且右子树长高 { switch((*T)->BF) { case LH://原本左子树比右子树高,现在左右子树等高 (*T)->BF=EH; *taller=0; break; case EH://原本左右子树等高,现在右子树变高 (*T)->BF=RH; *taller=1; break; case RH://原本右子树比左子树高,现在需做右平衡处理 RightBalance(T); *taller=0; break; } } } } return 1;}int Find(BTree T,int key){ if(!T) return 0; else if(T->data==key) return 1; else if(T->data<key) return Find(T->rchild,key); else return Find(T->lchild,key);}void Output(BTree T){ if(T) { printf("%d",T->data); if(T->lchild||T->rchild) { printf("("); Output(T->lchild); printf(","); Output(T->rchild); printf(")"); } }}int main(int argc,char *argv[]){ int i; int A[]={3,2,1,4,5,6,7,10,9,8}; BTree T=NULL; int taller; for(i=0;i<sizeof(A)/sizeof(int);i++) InsertAVL(&T,A[i],&taller); Output(T); printf("\n"); if(Find(T,6)) printf("6 is find in the AVL tree!\n"); else printf("6 is not find in the AVL tree!\n"); return 0;}
- 平衡二叉树平衡法则
- 二叉树--二叉平衡树
- 平衡二叉树的
- 平衡二叉树
- 平衡二叉树
- 平衡二叉树
- 平衡二叉树
- 平衡二叉查找树
- 平衡二叉树 详解
- 平衡二叉树
- 平衡二叉树
- AVL 平衡二叉树
- 平衡二叉树
- 平衡二叉树-红黑树
- 平衡二叉树
- 平衡二叉树
- 平衡二叉树
- 平衡二叉树
- BOBSLEDDING (nyoj309)
- ExtJS4学习笔记八--Template的使用
- 搜索矩阵
- 透析Java本质-类的初始化顺序
- ubuntu 12.04无法进入图形界面
- 平衡二叉树
- DeviceIoControl的返回结果判断
- java 连接sql server 2008
- 为什么不去读顶级会议上的论文?适应于机器学习、计算机视觉和人工智能
- JS正则表达式大全
- 梦想
- oracle体系结构详解
- iOS开发缓存:内存缓存
- 让 VB6 开发的程序拥有视觉样式( XP 风格),VC++6.0 同样适用