平衡二叉树操作演示
数据结构平衡二叉树的操作演示

平衡二叉树操作的演示1.需求分析本程序是利用平衡二叉树,实现动态查找表的基本功能:创建表,查找、插入、删除。
具体功能:(1)初始,平衡二叉树为空树,操作界面给出创建、查找、插入、删除、合并、分裂六种操作供选择。
每种操作均提示输入关键字。
每次插入或删除一个结点后,更新平衡二叉树的显示。
(2)平衡二叉树的显示采用凹入表现形式。
(3)合并两棵平衡二叉树。
(4)把一棵二叉树分裂为两棵平衡二叉树,使得在一棵树中的所有关键字都小于或等于x,另一棵树中的任一关键字都大于x。
如下图:2.概要设计平衡二叉树是在构造二叉排序树的过程中,每当插入一个新结点时,首先检查是否因插入新结点而破坏了二叉排序树的平衡性,若是则找出其中的最小不平衡子树,在保持二叉排序树特性的前提下,调整最小不平衡子树中各结点之间的链接关系,进行相应的旋转,使之成为新的平衡子树。
具体步骤:(1)每当插入一个新结点,从该结点开始向上计算各结点的平衡因子,即计算该结点的祖先结点的平衡因子,若该结点的祖先结点的平衡因子的绝对值不超过1,则平衡二叉树没有失去平衡,继续插入结点;(2)若插入结点的某祖先结点的平衡因子的绝对值大于1,则找出其中最小不平衡子树的根结点;(3)判断新插入的结点与最小不平衡子树的根结点个关系,确定是那种类型的调整;(4)如果是LL型或RR型,只需应用扁担原理旋转一次,在旋转过程中,如果出现冲突,应用旋转优先原则调整冲突;如果是LR型或RL型,则需应用扁担原理旋转两次,第一次最小不平衡子树的根结点先不动,调整插入结点所在子树,第二次再调整最小不平衡子树,在旋转过程中,如果出现冲突,应用旋转优先原则调整冲突;(5)计算调整后的平衡二叉树中各结点的平衡因子,检验是否因为旋转而破坏其他结点的平衡因子,以及调整后平衡二叉树中是否存在平衡因子大于1的结点。
流程图3.详细设计二叉树类型定义:typedef int Status;typedef int ElemType;typedef struct BSTNode{ElemType data;int bf;struct BSTNode *lchild ,*rchild;} BSTNode,* BSTree;Status SearchBST(BSTree T,ElemType e)//查找void R_Rotate(BSTree &p)//右旋void L_Rotate(BSTree &p)//左旋void LeftBalance(BSTree &T)//插入平衡调整void RightBalance(BSTree &T)//插入平衡调整Status InsertAVL(BSTree &T,ElemType e,int &taller)//插入void DELeftBalance(BSTree &T)//删除平衡调整void DERightBalance(BSTree &T)//删除平衡调整Status Delete(BSTree &T,int &shorter)//删除操作Status DeleteAVL(BSTree &T,ElemType e,int &shorter)//删除操作void merge(BSTree &T1,BSTree &T2)//合并操作void splitBSTree(BSTree T,ElemType e,BSTree &T1,BSTree &T2)//分裂操作void PrintBSTree(BSTree &T,int lev)//凹入表显示附录源代码:#include<stdio.h>#include<stdlib.h>//#define TRUE 1//#define FALSE 0//#define OK 1//#define ERROR 0#define LH +1#define EH 0#define RH -1//二叉类型树的类型定义typedef int Status;typedef int ElemType;typedef struct BSTNode{ElemType data;int bf;//结点的平衡因子struct BSTNode *lchild ,*rchild;//左、右孩子指针} BSTNode,* BSTree;/*查找算法*/Status SearchBST(BSTree T,ElemType e){if(!T){return 0; //查找失败}else if(e == T->data ){return 1; //查找成功}else if (e < T->data){return SearchBST(T->lchild,e);}else{return SearchBST(T->rchild,e);}}//右旋void R_Rotate(BSTree &p){BSTree lc; //处理之前的左子树根结点lc = p->lchild; //lc指向的*p的左子树根结点p->lchild = lc->rchild; //lc的右子树挂接为*P的左子树lc->rchild = p;p = lc; //p指向新的根结点}//左旋void L_Rotate(BSTree &p){BSTree rc;rc = p->rchild; //rc指向的*p的右子树根结点p->rchild = rc->lchild; //rc的左子树挂接为*p的右子树rc->lchild = p;p = rc; //p指向新的根结点}//对以指针T所指结点为根结点的二叉树作左平衡旋转处理,//本算法结束时指针T指向新的根结点void LeftBalance(BSTree &T){BSTree lc,rd;lc=T->lchild;//lc指向*T的左子树根结点switch(lc->bf){ //检查*T的左子树的平衡度,并做相应的平衡处理case LH: //新结点插入在*T的左孩子的左子树,要做单右旋处理T->bf = lc->bf=EH;R_Rotate(T);break;case RH: //新结点插入在*T的左孩子的右子树上,做双旋处理rd=lc->rchild; //rd指向*T的左孩子的右子树根switch(rd->bf){ //修改*T及其左孩子的平衡因子case LH: T->bf=RH; lc->bf=EH;break;case EH: T->bf=lc->bf=EH;break;case RH: T->bf=EH; lc->bf=LH;break;}rd->bf=EH;L_Rotate(T->lchild); //对*T的左子树作左旋平衡处理R_Rotate(T); //对*T作右旋平衡处理}}//右平衡旋转处理void RightBalance(BSTree &T){BSTree rc,ld;rc=T->rchild;switch(rc->bf){case RH:T->bf= rc->bf=EH;L_Rotate(T);break;case LH:ld=rc->lchild;switch(ld->bf){case LH: T->bf=RH; rc->bf=EH;break;case EH: T->bf=rc->bf=EH;break;case RH: T->bf = EH; rc->bf=LH;break;}ld->bf=EH;R_Rotate(T->rchild);L_Rotate(T);}}//插入结点Status InsertAVL(BSTree &T,ElemType e,int &taller){//taller反应T长高与否if(!T){//插入新结点,树长高,置taller为trueT= (BSTree) malloc (sizeof(BSTNode));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)//已插入到*T的左子树中且左子树长高switch(T->bf){//检查*T的平衡度,作相应的平衡处理case LH:LeftBalance(T);taller = 0;break;case EH:T->bf = LH;taller = 1;break;case RH:T->bf = EH;taller = 0;break;}}else{if (!InsertAVL(T->rchild,e,taller)){return 0;}if(taller)//插入到*T的右子树且右子树增高switch(T->bf){//检查*T的平衡度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;}void DELeftBalance(BSTree &T){//删除平衡调整BSTree lc,rd;lc=T->lchild;switch(lc->bf){case LH:T->bf = EH;//lc->bf= EH;R_Rotate(T);break;case EH:T->bf = EH;lc->bf= EH;R_Rotate(T);break;case RH:rd=lc->rchild;switch(rd->bf){case LH: T->bf=RH; lc->bf=EH;break;case EH: T->bf=lc->bf=EH;break;case RH: T->bf=EH; lc->bf=LH;break;}rd->bf=EH;L_Rotate(T->lchild);R_Rotate(T);}}void DERightBalance(BSTree &T) //删除平衡调整{BSTree rc,ld;rc=T->rchild;switch(rc->bf){case RH:T->bf= EH;//rc->bf= EH;L_Rotate(T);break;case EH:T->bf= EH;//rc->bf= EH;L_Rotate(T);break;case LH:ld=rc->lchild;switch(ld->bf){case LH: T->bf=RH; rc->bf=EH;break;case EH: T->bf=rc->bf=EH;break;case RH: T->bf = EH; rc->bf=LH;break;}ld->bf=EH;R_Rotate(T->rchild);L_Rotate(T);}}void SDelete(BSTree &T,BSTree &q,BSTree &s,int &shorter){if(s->rchild){SDelete(T,s,s->rchild,shorter);if(shorter)switch(s->bf){case EH:s->bf = LH;shorter = 0;break;case RH:s->bf = EH;shorter = 1;break;case LH:DELeftBalance(s);shorter = 0;break;}return;}T->data = s->data;if(q != T)q->rchild = s->lchild;elseq->lchild = s->lchild;shorter = 1;}//删除结点Status Delete(BSTree &T,int &shorter){ BSTree q;if(!T->rchild){q = T;T = T->lchild;free(q);shorter = 1;}else if(!T->lchild){q = T;T= T->rchild;free(q);shorter = 1;}else{SDelete(T,T,T->lchild,shorter);if(shorter)switch(T->bf){case EH:T->bf = RH;shorter = 0;break;case LH:T->bf = EH;shorter = 1;break;case RH:DERightBalance(T);shorter = 0;break;}}return 1;}Status DeleteAVL(BSTree &T,ElemType e,int &shorter){ int sign = 0;if (!T){return sign;}else{if(e == T->data){sign = Delete(T,shorter);return sign;}else if(e < T->data){sign = DeleteAVL(T->lchild,e,shorter);if(shorter)switch(T->bf){case EH:T->bf = RH;shorter = 0;break;case LH:T->bf = EH;shorter = 1;break;case RH:DERightBalance(T);shorter = 0;break;}return sign;}else{sign = DeleteAVL(T->rchild,e,shorter);if(shorter)switch(T->bf){case EH:T->bf = LH;shorter = 0;break;case RH:T->bf = EH;break;case LH:DELeftBalance(T);shorter = 0;break;}return sign;}}}//合并void merge(BSTree &T1,BSTree &T2){int taller = 0;if(!T2)return;merge(T1,T2->lchild);InsertAVL(T1,T2->data,taller);merge(T1,T2->rchild);}//分裂void split(BSTree T,ElemType e,BSTree &T1,BSTree &T2){ int taller = 0;if(!T)return;split(T->lchild,e,T1,T2);if(T->data > e)InsertAVL(T2,T->data,taller);elseInsertAVL(T1,T->data,taller);split(T->rchild,e,T1,T2);}//分裂void splitBSTree(BSTree T,ElemType e,BSTree &T1,BSTree &T2){ BSTree t1 = NULL,t2 = NULL;split(T,e,t1,t2);T1 = t1;T2 = t2;return;}//构建void CreatBSTree(BSTree &T){int num,i,e,taller = 0;printf("输入结点个数:");scanf("%d",&num);printf("请顺序输入结点值\n");for(i = 0 ;i < num;i++){printf("第%d个结点的值",i+1);scanf("%d",&e);InsertAVL(T,e,taller) ;}printf("构建成功,输入任意字符返回\n");getchar();getchar();}//凹入表形式显示方法void PrintBSTree(BSTree &T,int lev){int i;if(T->rchild)PrintBSTree(T->rchild,lev+1);for(i = 0;i < lev;i++)printf(" ");printf("%d\n",T->data);if(T->lchild)PrintBSTree(T->lchild,lev+1);void Start(BSTree &T1,BSTree &T2){int cho,taller,e,k;taller = 0;k = 0;while(1){system("cls");printf(" 平衡二叉树操作的演示 \n\n");printf("********************************\n");printf(" 平衡二叉树显示区 \n");printf("T1树\n");if(!T1 )printf("\n 当前为空树\n");else{PrintBSTree(T1,1);}printf("T2树\n");if(!T2 )printf("\n 当前为空树\n");elsePrintBSTree(T2,1);printf("\n********************************************************************* *********\n");printf("T1操作:1.创建 2.插入 3.查找 4.删除 10.分裂\n");printf("T2操作:5.创建 6.插入 7.查找 8.删除 11.分裂\n");printf(" 9.合并 T1,T2 0.退出\n");printf("*********************************************************************** *******\n");printf("输入你要进行的操作:");scanf("%d",&cho);switch(cho){case 1:CreatBSTree(T1);break;case 2:printf("请输入要插入关键字的值");scanf("%d",&e);InsertAVL(T1,e,taller) ;break;case 3:printf("请输入要查找关键字的值");scanf("%d",&e);if(SearchBST(T1,e))printf("查找成功!\n");elseprintf("查找失败!\n");printf("按任意键返回87"); getchar();getchar();break;case 4:printf("请输入要删除关键字的值"); scanf("%d",&e);if(DeleteAVL(T1,e,k))printf("删除成功!\n");elseprintf("删除失败!\n");printf("按任意键返回");getchar();getchar();break;case 5:CreatBSTree(T2);break;case 6:printf("请输入要插入关键字的值"); scanf("%d",&e);InsertAVL(T2,e,taller) ;break;case 7:printf("请输入要查找关键字的值"); scanf("%d",&e);if(SearchBST(T2,e))printf("查找成功!\n");elseprintf("查找失败!\n");printf("按任意键返回");getchar();getchar();break;case 8:printf("请输入要删除关键字的值"); scanf("%d",&e);if(DeleteAVL(T2,e,k))printf("删除成功!\n");elseprintf("删除失败!\n");printf("按任意键返回");getchar();getchar();break;case 9:merge(T1,T2);T2 = NULL;printf("合并成功,按任意键返回"); getchar();getchar();break;case 10:printf("请输入要中间值字的值"); scanf("%d",&e);splitBSTree(T1,e,T1,T2) ;printf("分裂成功,按任意键返回"); getchar();getchar();break;case 11:printf("请输入要中间值字的值"); scanf("%d",&e);splitBSTree(T2,e,T1,T2) ;printf("分裂成功,按任意键返回"); getchar();getchar();break;case 0:system("cls");exit(0);}}}main(){BSTree T1 = NULL;BSTree T2 = NULL;Start(T1,T2);}。
平衡二叉树10.3.2

11
28
96 98
25
(1) LL型调整 型调整 p A 1 2
调整方法: 调整方法: 单向右旋平衡,即将 的左孩子 单向右旋平衡,即将A的左孩子 B 向右上旋转代替 成为根结点, 向右上旋转代替A成为根结点 成为根结点, 结点向右下旋转成为B的右 将A结点向右下旋转成为 的右 结点向右下旋转成为 子树的根结点, 子树的根结点,而B的原右子树 的原右子树 则作为A结点的左子树 结点的左子树. 则作为 结点的左子树. h d e B
1 38 -1 24 88
0 -1 -2
0
11
28 1
96
0
-1 0
25
0
98
1,平衡二叉树插入结点的调整方法
若向平衡二叉树中插入一个新结点后破坏了平衡二叉树的平衡性, 若向平衡二叉树中插入一个新结点后破坏了平衡二叉树的平衡性, 首先从根结点到该新插入结点的路径之逆向根结点方向找第一个失去平 衡的结点, 衡的结点,然后以该失衡结点和它相邻的刚查找过的两个结点构成调整 子树(最小不平衡子树 即调整子树是指以离插入结点最近,且平衡因子 最小不平衡子树), 子树 最小不平衡子树 ,即调整子树是指以离插入结点最近 且平衡因子 绝对值大于1的结点为根结点的子树 使之成为新的平衡子树. 的结点为根结点的子树,使之成为新的平衡子树 绝对值大于 的结点为根结点的子树 使之成为新的平衡子树. 38 24 88 -2
(2)RR型调整 型调整 p A -1 -2
调整方法: 调整方法: 单向左旋平衡:即将 的右孩子 的右孩子B向 单向左旋平衡:即将A的右孩子 向 左上旋转代替A成为根结点 成为根结点, 左上旋转代替 成为根结点,将A结 结 点向左下旋转成为B的左子树的根 点向左下旋转成为 的左子树的根 结点, 的原左子树则作为A结点 结点,而B的原左子树则作为 结点 的原左子树则作为 的右子树. 的右子树. B
详解平衡二叉树

一、平衡二叉树的概念平衡二叉树(Balanced binary tree)是由阿德尔森-维尔斯和兰迪斯(Adelson-Velskii and Landis)于1962年首先提出的,所以又称为AVL树。
定义:平衡二叉树或为空树,或为如下性质的二叉排序树:(1)左右子树深度之差的绝对值不超过1;(2)左右子树仍然为平衡二叉树.平衡因子BF=左子树深度-右子树深度.平衡二叉树每个结点的平衡因子只能是1,0,-1。
若其绝对值超过1,则该二叉排序树就是不平衡的。
如图所示为平衡树和非平衡树示意图:二、平衡二叉树算法思想若向平衡二叉树中插入一个新结点后破坏了平衡二叉树的平衡性。
首先要找出插入新结点后失去平衡的最小子树根结点的指针。
然后再调整这个子树中有关结点之间的链接关系,使之成为新的平衡子树。
当失去平衡的最小子树被调整为平衡子树后,原有其他所有不平衡子树无需调整,整个二叉排序树就又成为一棵平衡二叉树。
失去平衡的最小子树是指以离插入结点最近,且平衡因子绝对值大于1的结点作为根的子树。
假设用A表示失去平衡的最小子树的根结点,则调整该子树的操作可归纳为下列四种情况。
1)LL型平衡旋转法由于在A的左孩子B的左子树上插入结点F,使A的平衡因子由1增至2而失去平衡。
故需进行一次顺时针旋转操作。
即将A的左孩子B向右上旋转代替A作为根结点,A向右下旋转成为B的右子树的根结点。
而原来B的右子树则变成A的左子树。
(2)RR型平衡旋转法由于在A的右孩子C 的右子树上插入结点F,使A的平衡因子由-1减至-2而失去平衡。
故需进行一次逆时针旋转操作。
即将A的右孩子C向左上旋转代替A作为根结点,A向左下旋转成为C的左子树的根结点。
而原来C的左子树则变成A的右子树。
(3)LR型平衡旋转法由于在A的左孩子B的右子数上插入结点F,使A的平衡因子由1增至2而失去平衡。
故需进行两次旋转操作(先逆时针,后顺时针)。
即先将A结点的左孩子B的右子树的根结点D向左上旋转提升到B结点的位置,然后再把该D结点向右上旋转提升到A结点的位置。
《二叉树的概念》课件

05
二叉树的应用
Chapter
在数据结构中的应用
二叉搜索树
二叉搜索树是一种特殊的二叉树,它的每个节点的左子树上的所有元素都小于 该节点,右子树上的所有元素都大于该节点。这种数据结构可以用于快速查找 、插入和删除操作。
AVL树和红黑树
这两种二叉树都是自平衡二叉搜索树,它们通过调整节点的左右子树的高度来 保持树的平衡,从而在插入、删除等操作时具有较好的性能。
VS
详细描述
平衡二叉树的特点是,它的左右子树的高 度差不会超过1,且左右子树都是平衡二 叉树。平衡二叉树的性质还包括,它的所 有叶节点的层数相等,且所有非叶节点的 左右子树的高度差不超过1。平衡二叉树 的查找、插入和删除操作的时间复杂度为 O(log n),其中n为节点数。
04
二叉树的遍历
Chapter
决策树
在机器学习和人工智能领域,决策树 是一种重要的分类和回归方法。其基 础结构就是二叉树,通过构建决策树 ,可以解决分类和回归问题。
THANKS
感谢观看
代码表示法
总结词:严谨规范
详细描述:使用编程语言的语法结构来表示二叉树,每个节点用对象或结构体表示,节点间的关系通 过指针或引用表示,严谨规范,易于编写和调试。
03
二叉树的性质
Chapter
深度最大的二叉树
总结词
深度最大的二叉树是指具有最大 可能深度的二叉树。
详细描述
在二叉树中,深度最大的二叉树 是满二叉树,即每个层级都完全 填满,没有空缺的节点。满二叉 树的深度等于其节点总数减一。
02
二叉树的表示方法
Chapter
图形表示法
总结词:直观明了
详细描述:通过图形的方式展示二叉树的结构,每个节点用圆圈或方框表示,节 点间的关系用线段表示,直观易懂,易于理解。
平衡二叉树

构造二叉平衡(查找)树的方法是:
在插入过程中,采用平衡旋转技术。
例如:依次插入的关键字为5, 4, 2, 8, 6, 9
5 4 2
向右旋转 一次
4 2 5 8 2
4 6 5
先向右旋转 再向左旋转
8
6
向左旋转一次
4 2 5 6 8 9 4 6 8 5 9
继续插入关键字 9
2
④平衡调整 假设由于在二叉排序树上插入结点而失去平衡的最小子树 根结点的指针为a(即a是离插入结点最近,且平衡因子绝对值 超过1的祖先结点),则失去平衡后进行调整的规律可归纳为下 列4种情况: 1.单向右旋平衡处理: 由于在*a的左子树根结点的左子树上插入结点,*a的平衡 因子由1增至2,致使以*a为根的子树失去平衡,则需进行一次 向右的顺时针旋转操作。如图9.6(a)所示。
0 C
RL
0 A AL CL CR
-1 B BR
插入结点
⑤插入算法 算法思想: 在平衡二叉排序树BBST上插入一个新的数据元素e的递归算法 可描述如下: 1.若BBST为空树,则插入一个数据元素为e的新结点作为 BBST的根结 点,树的深度增1; 2.若e的关键字和BBST的根结点的关键字相等,则不进行插入; 3.若e的关键字小于BBST的根结点的关键字,而且在BBST的 左子树中不存在和e有相同关键字的结点,则将e插入在BBST的 左子树上,并且当插入之后的左子树深度增加(+1)时,分别 就下列不同情况处理之:
p
lc
算法9.10如下:
#define #define #define
LH EH RH
+1 0 -1
//左高 //等高 //右高
Status InsertAVL (BSTree &T, ElemType e, Boolean &taller) { //若在平衡的二叉排序树T中不存在和e有相同关键字的结点,则插入 //一个数据元素为e的新结点,并返回1,否则返回0。若因插入而使二 //叉排序树失去平衡,则作平衡旋转处理,布尔变量taller反映T长高 //与否。
平衡二叉树实现代码

平衡二叉树实现代码平衡二叉树(Balanced Binary Tree),也叫 AVL 树,是一种特殊的二叉树,它的每个节点的左子树和右子树的高度差不超过1、当插入或删除一个节点后,如果导致树的不平衡,就通过旋转操作来恢复平衡。
下面是平衡二叉树的实现代码:```python#定义平衡二叉树的节点类class AVLNode:def __init__(self, key):self.key = keyself.left = Noneself.right = Noneself.height = 1#定义平衡二叉树类class AVLTree:def __init__(self):self.root = None#获取节点的高度def get_height(self, node):if node is None:return 0return node.height#计算平衡因子def get_balance(self, node):if node is None:return 0return self.get_height(node.left) -self.get_height(node.right)#左旋操作def left_rotate(self, z):y = z.rightT2 = y.lefty.left = zz.right = T2z.height = 1 + max(self.get_height(z.left), self.get_height(z.right))y.height = 1 + max(self.get_height(y.left), self.get_height(y.right))return y#右旋操作def right_rotate(self, z):y = z.leftT3 = y.righty.right = zz.left = T3z.height = 1 + max(self.get_height(z.left), self.get_height(z.right))y.height = 1 + max(self.get_height(y.left), self.get_height(y.right))return y#插入节点def insert(self, key):def insert_node(node, key):if node is None:return AVLNode(key)elif key < node.key:node.left = insert_node(node.left, key)else:node.right = insert_node(node.right, key)node.height = 1 + max(self.get_height(node.left), self.get_height(node.right))balance = self.get_balance(node)#如果节点不平衡,进行旋转操作来恢复平衡if balance > 1:if key < node.left.key:return self.right_rotate(node)else:node.left = self.left_rotate(node.left)return self.right_rotate(node)if balance < -1:if key > node.right.key:return self.left_rotate(node)else:node.right = self.right_rotate(node.right)return self.left_rotate(node)return nodeself.root = insert_node(self.root, key)#删除节点def delete(self, key):def delete_node(node, key):if node is None:return nodeelif key < node.key:node.left = delete_node(node.left, key) elif key > node.key:node.right = delete_node(node.right, key) else:if node.left is None:temp = node.rightnode = Nonereturn tempelif node.right is None:temp = node.leftnode = Nonereturn temptemp = self.get_min_value_node(node.right)node.key = temp.keynode.right = delete_node(node.right, temp.key)if node is None:return nodenode.height = 1 + max(self.get_height(node.left), self.get_height(node.right))balance = self.get_balance(node)#如果节点不平衡,进行旋转操作来恢复平衡if balance > 1:if self.get_balance(node.left) >= 0:return self.right_rotate(node)else:node.left = self.left_rotate(node.left)return self.right_rotate(node)if balance < -1:if self.get_balance(node.right) <= 0:return self.left_rotate(node)else:node.right = self.right_rotate(node.right)return self.left_rotate(node)return nodeself.root = delete_node(self.root, key) #获取以一些节点为根的子树中的最小值节点def get_min_value_node(self, node):if node is None or node.left is None: return nodereturn self.get_min_value_node(node.left) #中序遍历树def inorder_traversal(self):def inorder(node):if node is None:returninorder(node.left)print(node.key, end=" ")inorder(node.right)inorder(self.root)#测试代码if __name__ == '__main__':tree = AVLTreenodes = [50, 30, 70, 20, 40, 60, 80, 25, 10, 55]for node in nodes:tree.insert(node)print("平衡二叉树中序遍历结果:")tree.inorder_traversalprint("\n删除节点 40 后的平衡二叉树中序遍历结果:")tree.delete(40)tree.inorder_traversal```以上就是平衡二叉树的实现代码,代码中包含了平衡二叉树节点类的定义,以及插入节点、删除节点、左旋和右旋操作等方法的实现。
一颗平衡二叉树非叶结点平衡因子1

一颗平衡二叉树非叶结点平衡因子1
平衡二叉树是一种特殊的二叉树,它的左右子树的高度差不大于1。
平衡二叉树的出现是为了解决二叉查找树在频繁插入和删除节点时出现的不平衡问题,使得树的高度保持在O(logN)级别。
而平衡因子是指一颗节点的左右子树高度差,平衡因子等于1的平衡二叉树非叶结点是一种特殊的平衡二叉树。
平衡因子等于1的平衡二叉树非叶结点,是指该节点的左右子树高度相差1。
这种平衡二叉树的特点是,左右子树的高度差为1,且左右子树都是平衡二叉树。
这样一来,这种平衡因子等于1的平衡二叉树非叶结点就具有了一些特殊的性质。
首先,这种平衡因子等于1的平衡二叉树非叶结点,它的左右子树高度相差1,这表明左子树的高度和右子树的高度非常接近。
这种接近性质使得这种平衡因子等于1的平衡二叉树非叶结点能够更好
地平衡左右子树之间的权重,使得插入和删除操作更稳定,效率更高。
其次,这种平衡因子等于1的平衡二叉树非叶结点,它的左右子树都是平衡二叉树,这就意味着左右子树的高度差不大于1,且左右子树都是平衡的,这使得这种平衡因子等于1的平衡二叉树非叶结点具有更好的平衡性和更高的效率。
最后,这种平衡因子等于1的平衡二叉树非叶结点在平衡二叉树的操作中具有很重要的作用。
因为非叶结点是平衡二叉树中最重要的部分,它的平衡因子等于1能够更好地平衡左右子树之间的权重,防止因插入或删除节点而导致的树的不平衡。
总之,平衡因子等于1的平衡二叉树非叶结点是一种特殊的平衡二叉树。
它具有接近性质、平衡性和高效性,是平衡二叉树中最重要的部分。
在平衡二叉树的操作中,我们要注意维护它的平衡性,保证左右子树的平衡因子相差不大于1,以保证平衡二叉树的效率。
平衡二叉树调整算法

平衡二叉树调整算法在平衡二叉树中插入一个结点后造成不平衡,设最低的不平衡结点为A,并已知A的左孩子平衡因子为0,右孩子平衡因子为1,则应该做(C)型调整以使其平衡A LLB LRC RLD RR若向平衡二叉树中插入一个新结点后破坏了平衡二叉树的平衡性。
首先要找出插入新结点后失去平衡的最小子树根结点的指针。
然后再调整这个子树中有关结点之间的链接关系,使之成为新的平衡子树。
当失去平衡的最小子树被调整为平衡子树后,原有其他所有不平衡子树无需调整,整个二叉排序树就又成为一棵平衡二叉树。
失去平衡的最小子树是指以离插入结点最近,且平衡因子绝对值大于 1 的结点作为根的子树。
假设用 A 表示失去平衡的最小子树的根结点,则调整该子树的操作可归纳为下列四种情况。
(1)LL型平衡旋转法由于在 A 的左孩子 B 的左子树上插入结点 F ,使 A 的平衡因子由 1 增至2 而失去平衡。
故需进行一次顺时针旋转操作。
即将 A 的左孩子 B 向右上旋转代替 A 作为根结点, A 向右下旋转成为 B 的右子树的根结点。
而原来B 的右子树则变成 A 的左子树。
(2)RR型平衡旋转法由于在 A 的右孩子 C 的右子树上插入结点 F ,使 A 的平衡因子由-1 减至-2 而失去平衡。
故需进行一次逆时针旋转操作。
即将 A 的右孩子 C 向左上旋转代替 A 作为根结点, A 向左下旋转成为 C 的左子树的根结点。
而原来C 的左子树则变成 A 的右子树。
(3)LR型平衡旋转法由于在 A 的左孩子 B 的右子数上插入结点 F ,使 A 的平衡因子由 1 增至2 而失去平衡。
故需进行两次旋转操作(先逆时针,后顺时针)。
即先将A 结点的左孩子B 的右子树的根结点 D 向左上旋转提升到 B 结点的位置,然后再把该D 结点向右上旋转提升到 A 结点的位置。
即先使之成为LL型,再按LL型处理。
如图中所示,即先将圆圈部分先调整为平衡树,然后将其以根结点接到 A 的左子树上,此时成为LL 型,再按LL 型处理成平衡型。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
数据结构实习报告题目:平衡二叉树的操作演示班级:信息管理与信息系统11-1姓名:崔佳学号:3完成日期:2013.06.25一、需求分析1. 初始,平衡二叉树为空树,操作界面给出两棵平衡二叉树的显示、查找、插入、删除、销毁、合并两棵树,几种选择。
其中查找、插入和删除操作均要提示用户输入关键字。
每次插入或删除一个节点后都会更新平衡二叉树的显示。
2. 平衡二叉树的显示采用凹入表形式。
3.每次操作完毕后都会给出相应的操作结果,并进入下一次操作,知道用户选择退出二、概要设计1.平衡二叉树的抽象数据类型定义:ADT BalancedBinaryTree{数据对象D:D是具有相同特性的数据元素的集合。
各个数据元素均含有类型相同,可唯一标志的数据元素的关键字。
数据关系R:数据元素同属一个集合。
基本操作P:InitAVL(BSTree& T)操作结果:构造一个空的平衡二叉树TDestroyAVL(BSTree& T)初始条件:平衡二叉树T存在操作结果:销毁平衡二叉树TSearchAVL(BSTree T,int key)初始条件:平衡二叉树T存在,key为和关键字相同类型的给定值操作结果:若T中存在关键字和key相等的数据元素,则返回指向该元素的指针,否则为空InsertAVL(BSTree& T,int key,Status& taller)初始条件:平衡二叉树T存在,key和关键字的类型相同操作结果:若T中存在关键字等于key的数据元素则返回,若不存在则插入一个关键字为key的元素DeleteAVL(BSTree& T,int &key,Status& lower)初始条件:平衡二叉树T存在,key和关键字的类型相同操作结果:若T中存在关键字和key相同的数据元素则删除它}ADT BalancedBinaryTree2.本程序包含二个模块1)主程序模块:void main(){接收命令;While(“命令”!=“退出”){处理命令;清屏并得新打印提示信息;接收下一条命令;}}2)平衡二叉树基本操作实现平衡二叉树的抽象数据类型的各函数原型。
各模块之间的调用关系如下:主程序模块平衡二叉树模块三、详细设计1. 根据题目要求和平衡二叉树的操作特点,平衡二叉树采用整数链式存储结构基本操作的函数原型:#define LH 1 //左高#define EH 0 //等高#define RH -1 //右高#define TRUE 1#define FALSE 0#define ERROR 0#define OK 1typedef int Status;typedef int ElemType; //本程序处理数据对象为整型typedef struct BSTNode{ElemType data;int bf;struct BSTNode *lchild,*rchild;}BSTNode,*BSTree;1)平衡二叉树基本操作实现//构造平衡二叉树TStatus InitAVL(BSTree &T){T=NULL;return OK;}//对以*p为根的二叉树作左旋处理,处理之后p指向新的树根结点//即旋转处理之前的右子树的根结点void L_Rotate(BSTree &p){BSTree rc;rc=p->rchild;p->rchild=rc->lchild;rc->lchild=p; p=rc;}//对以*p为根的二叉树作右旋处理,处理之后p指向新的树根结点//即旋转处理之前的左子树的根结点void R_Rotate(BSTree &p){BSTree lc;lc=p->lchild;p->lchild=lc->rchild;lc->rchild=p; p=lc;}//对以指针T所指结点为根的二叉树作右平衡处理//本算法结束时T指向新的根结点void LeftBalance(BSTree &T){BSTree lc,rd;lc=T->lchild;switch(lc->bf){case LH:T->bf=lc->bf=EH;R_Rotate(T); break;case RH:rd=lc->rchild;switch(rd->bf){case LH:T->bf=RH; lc->bf=EH; break;case EH:T->bf=lc->bf=EH; break;case RH:T->bf=EH; lc->bf=LH; break;}rd->bf=EH;L_Rotate(T->lchild);R_Rotate(T);}}//对以指针T所指结点为根的二叉树作右平衡处理//本算法结束时T指向新的根结点void RightBalance(BSTree& T){BSTree rc,rd;rc=T->rchild;switch(rc->bf){case RH: T->bf=rc->bf=EH;L_Rotate(T);break;case LH: rd=rc->lchild;switch(rd->bf){case RH:T->bf=LH; rc->bf=EH; break;case EH:T->bf=rc->bf=EH; break;case LH:T->bf=EH; rc->bf=RH; break;}rd->bf=EH;R_Rotate(T->rchild);L_Rotate(T);}}//查找关键字为key的结点//如有返回指向此结点的指针,如无返回空Status SearchAVL(BSTree T,int e){if(!T) return ERROR;if(T->data==e){printf("\t结果: %d[%d]\n\t",T->data,T->bf);return OK;}else{if(T->lchild)if(SearchAVL(T->lchild,e))return OK;if(T->rchild)if(SearchAVL(T->rchild,e))return OK;return ERROR;}}//若在平衡的二叉排序树中不存在和e相同的关键字的结点,则插入一个数据元素为e的新结点并返回1,否则返回0。
//若因插入而使二叉排序树失去平衡,则做平衡旋转处理//布尔变量taller反映T长高与否Status InsertAVL(BSTree &T,ElemType e,Status &taller){if(!T){T=(BSTree)malloc(sizeof(BSTNode));T->data=e;T->lchild=T->rchild=NULL;T->bf=EH;taller=TRUE;}else{if(e==T->data){taller=FALSE; return FALSE;}if(e<T->data){if(!InsertAVL(T->lchild,e,taller)) return FALSE;if(taller)switch(T->bf){case LH:LeftBalance(T); taller=FALSE; break;case EH:T->bf=LH; taller=TRUE; break;case RH:T->bf=EH; taller=FALSE; break;}}else{if(!InsertAVL(T->rchild,e,taller)) return FALSE;if(taller)switch(T->bf){case RH:RightBalance(T); taller=FALSE; break;case EH:T->bf=RH; taller=TRUE; break;case LH:T->bf=EH; taller=FALSE; break;}}}return TRUE;}//打印空格void Printblank(int i){while(i >=0){printf(" ");i--;}}//以凹入表的形式显示平衡二叉树Tvoid ViewTree(BSTree T,int i){if(T){ Printblank(i); printf("%d[%d]\n",T->data,T->bf);} else{ Printblank(i); printf("NULL\n"); return; }ViewTree(T->lchild,i+5);ViewTree(T->rchild,i+5);}//销毁平衡二叉树void DestroyAVL(BSTree &T){if(T){if(T->lchild)DestroyAVL(T->lchild);if(T->rchild)DestroyAVL(T->rchild);free(T);T=NULL;}}Status Delete(BSTree& p,int &e,int &flag){ BSTree q,s;if(!p->rchild){q=p;if(p->lchild){p->lchild->bf=p->bf;e=p->lchild->data;}p=p->lchild;free(q);flag=1;}else if(!p->lchild){q=p;p->rchild->bf=p->bf;e=p->rchild->data;p=p->rchild;free(q);flag=1;}else{q=p; s=p->lchild;while(s->rchild){q=s; s=s->rchild;}p->data=s->data;if(q!=p)q->rchild=s->lchild;else {q->lchild=s->lchild;p->bf=RH;}e=q->data;free(s);}return TRUE;}//若二叉排序树T中存在关键字等于e的数据元素时,则删除该数据元素结点//并返回TRUE,否则返回FALSEStatus DeleteBST(BSTree& T,int &e,int &flag){if(!T)return FALSE;else{if(e==T->data)return Delete(T,e,flag);else if(e<T->data) {if(!DeleteBST(T->lchild,e,flag)) return FALSE;return TRUE;}else {if(!DeleteBST(T->rchild,e,flag)) return FALSE;return TRUE;}}}void DelBalance(BSTree& T,int e, Status &lower,int &flag) {if(!T){lower=TRUE; return;}if(e==T->data){if(flag==1)switch(T->bf){case RH:case LH:T->bf=EH; lower=TRUE; break;}else switch(T->bf){case RH:lower=FALSE; break;case EH:T->bf=LH; lower=FALSE; break;case LH:LeftBalance(T); lower=TRUE; break;}return ;}if(e<T->data){DelBalance(T->lchild,e,lower,flag);if(lower)switch(T->bf){case LH:T->bf=EH; lower=TRUE; break;case EH:T->bf=RH; lower=FALSE; break;case RH:RightBalance(T); lower=TRUE; break;}}if(e>T->data){DelBalance(T->rchild,e,lower,flag);if(lower)switch(T->bf){case RH:T->bf=EH; lower=TRUE; break;case EH:T->bf=LH; lower=FALSE; break;case LH:LeftBalance(T); lower=TRUE; break;}}return ;}//删除平衡二叉树结点Status DeleteAVL(BSTree &T,int &e,Status &lower){ int flag=0;if(!DeleteBST(T,e,flag)) return FALSE;else DelBalance(T,e,lower,flag);return TRUE;}}2)主函数Main及其它辅助函数的实现/*主函数*/void main(){void Print();void About();BSTree T,t,p;int e,s; Status taller,lower;InitAVL(T);InitAVL(t);InitAVL(p);Print();scanf("%d",&s);while(s!=6){switch(s){case 1: //显示printf("按凹入表形式打印二叉树结构:\n");printf("T:\n");PrintTree(T,1);printf("t:\n");PrintTree(t,1);break;case 2: //查找printf("\t选择树(1,2):");scanf("%d",&s);printf("\t关键字(整数):");scanf("%d",&e);if(s==1) s=SearchAVL(T,e);if(s==2) s=SearchAVL(t,e);if(!s) printf("\t查找失败\n\t");break;case 3: //插入printf("\t选择树(1-T,2-t):");scanf("%d",&s);printf("\t关键字(整数):");scanf("%d",&e);if(s==1){InsertAVL(T,e,taller);printf("T:\n");PrintTree(T,1);}if(s==2){InsertAVL(t,e,taller);printf("t:\n");PrintTree(t,1);}break;case 4: //删除printf("\t选择树(1-T,2-t):");scanf("%d",&s);printf("\t关键字(整数):");scanf("%d",&e);if(s==1)if(DeleteAVL(T,e,lower))printf("\t删除成功\n\t");elseprintf("\t删除失败\n\t");if(s==2)if(DeleteAVL(t,e,lower))printf("\t删除成功\n\t");elseprintf("\t删除失败\n\t");break;case 5: //销毁printf("\t选择树(1,2):");scanf("%d",&s);if(s==1) DestroyAVL(T);if(s==2) DestroyAVL(t);printf("\t销毁成功\n\t");break;}system("pause");Print();scanf("%d",&s);}}void Print(){system("cls");printf(" ※※※※平衡二叉树操作演示※※※※\n");printf("\n");printf(" **************菜单**************** \n");printf(" * 1. 显示* \n");printf(" * 2. 查找* \n");printf(" * 3. 插入* \n");printf(" * 4. 删除* \n");printf(" * 5. 销毁* \n");printf(" * 6. 退出* \n");printf(" ********************************** \n");printf("请选择:\n");}3)函数之间的调用关系图:PrintTreeDelete四、调试分析1.本程序采用了凹表输出平衡二叉树各结点的关键字的值及平衡因子的值。