平衡二叉树操作演示

合集下载

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

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

平衡二叉树操作的演示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);}。

平衡二叉树和二叉排序树(二叉搜索树)区别

平衡二叉树和二叉排序树(二叉搜索树)区别

平衡⼆叉树和⼆叉排序树(⼆叉搜索树)区别
平衡⼆叉树是⼀种⼆叉搜索树。

其可以保证在log2(n)的时间内找到节点,⽽普通的⼆叉搜索树在最坏情况下性能近似与链
表,所⽤时间为log(n)。

常⽤的平衡⼆叉树有AVL树和红⿊树其算法的难点在于插⼊删除节点后树的旋转
平衡⼆叉树 ----> O(log2(n))
普通⼆叉搜索树 ----> O(n)
在⼆叉搜索树的插⼊和删除运算中,采⽤平衡树的优点是:使树的结构较好,从⽽提⾼查找运算的速度。

缺点是:是插⼊和删除运算变得复杂化,从⽽降低了他们的运算速度。

对⼆叉搜索树删除节点⽽引起的不平衡性进⾏的操作⽐插⼊节点的情况要复杂,在此就不再论述了。

操作系统的设计也有⽤到哦
很多数据库的实现是基于更复杂的平衡⼆叉树
可以⾃⼰实现⼀个集合或者map,统计单词出现的次数
stl的map/set都在⽤
普通⼆叉搜索树最坏情况是只有左边⼀个分⽀,如1-2-3-4-5(5在最上⾯,1在左下⾓),但是平衡⼆叉树可以调整。

为1-2-3-4-5(3在最上⾯,1在左下⾓,5在右下⾓)。

平衡⼆叉树 ----> O(log2(n))
普通⼆叉搜索树 ----> O(n)
所以平衡⼆叉树的搜索性能⽐⼆叉搜索树(⼆叉排序树)好。

平衡二叉树10.3.2

平衡二叉树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

数据结构与算法系列研究五——树、二叉树、三叉树、平衡排序二叉树AVL

数据结构与算法系列研究五——树、二叉树、三叉树、平衡排序二叉树AVL

数据结构与算法系列研究五——树、⼆叉树、三叉树、平衡排序⼆叉树AVL树、⼆叉树、三叉树、平衡排序⼆叉树AVL⼀、树的定义树是计算机算法最重要的⾮线性结构。

树中每个数据元素⾄多有⼀个直接前驱,但可以有多个直接后继。

树是⼀种以分⽀关系定义的层次结构。

a.树是n(≥0)结点组成的有限集合。

{N.沃恩}(树是n(n≥1)个结点组成的有限集合。

{D.E.Knuth})在任意⼀棵⾮空树中:⑴有且仅有⼀个没有前驱的结点----根(root)。

⑵当n>1时,其余结点有且仅有⼀个直接前驱。

⑶所有结点都可以有0个或多个后继。

b. 树是n(n≥0)个结点组成的有限集合。

在任意⼀棵⾮空树中:⑴有⼀个特定的称为根(root)的结点。

⑵当n>1时,其余结点分为m(m≥0)个互不相交的⼦集T1,T2,…,Tm。

每个集合本⾝⼜是⼀棵树,并且称为根的⼦树(subtree)树的固有特性---递归性。

即⾮空树是由若⼲棵⼦树组成,⽽⼦树⼜可以由若⼲棵更⼩的⼦树组成。

树的基本操作1、InitTree(&T) 初始化2、DestroyTree(&T) 撤消树3、CreatTree(&T,F) 按F的定义⽣成树4、ClearTree(&T) 清除5、TreeEmpty(T) 判树空6、TreeDepth(T) 求树的深度7、Root(T) 返回根结点8、Parent(T,x) 返回结点 x 的双亲9、Child(T,x,i) 返回结点 x 的第i 个孩⼦10、InsertChild(&T,&p,i,x) 把 x 插⼊到 P的第i棵⼦树处11、DeleteChild(&T,&p,i) 删除结点P的第i棵⼦树12、traverse(T) 遍历树的结点:包含⼀个数据元素及若⼲指向⼦树的分⽀。

●结点的度: 结点拥有⼦树的数⽬●叶结点: 度为零的结点●分枝结点: 度⾮零的结点●树的度: 树中各结点度的最⼤值●孩⼦: 树中某个结点的⼦树的根●双亲: 结点的直接前驱●兄弟: 同⼀双亲的孩⼦互称兄弟●祖先: 从根结点到某结点j 路径上的所有结点(不包括指定结点)。

详解平衡二叉树

详解平衡二叉树

一、平衡二叉树的概念平衡二叉树(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长高 //与否。

数据结构 -第12周查找第3讲-二叉排序树.pdf

数据结构 -第12周查找第3讲-二叉排序树.pdf

以二叉树或树作为表的组织形式,称为树表,它是一类动态查找表,不仅适合于数据查找,也适合于表插入和删除操作。

常见的树表:二叉排序树平衡二叉树B-树B+树9.3.1 二叉排序树二叉排序树(简称BST)又称二叉查找(搜索)树,其定义为:二叉排序树或者是空树,或者是满足如下性质(BST性质)的二叉树:❶若它的左子树非空,则左子树上所有节点值(指关键字值)均小于根节点值;❷若它的右子树非空,则右子树上所有节点值均大于根节点值;❸左、右子树本身又各是一棵二叉排序树。

注意:二叉排序树中没有相同关键字的节点。

二叉树结构满足BST性质:节点值约束二叉排序树503080209010854035252388例如:是二叉排序树。

66不试一试二叉排序树的中序遍历序列有什么特点?二叉排序树的节点类型如下:typedef struct node{KeyType key;//关键字项InfoType data;//其他数据域struct node*lchild,*rchild;//左右孩子指针}BSTNode;二叉排序树可看做是一个有序表,所以在二叉排序树上进行查找,和二分查找类似,也是一个逐步缩小查找范围的过程。

1、二叉排序树上的查找Nk< bt->keybtk> bt->key 每一层只和一个节点进行关键字比较!∧∧p查找到p所指节点若k<p->data,并且p->lchild=NULL,查找失败。

若k>p->data,并且p->rchild=NULL,查找失败。

查找失败的情况加上外部节点一个外部节点对应某内部节点的一个NULL指针递归查找算法SearchBST()如下(在二叉排序树bt上查找关键字为k的记录,成功时返回该节点指针,否则返回NULL):BSTNode*SearchBST(BSTNode*bt,KeyType k){if(bt==NULL||bt->key==k)//递归出口return bt;if(k<bt->key)return SearchBST(bt->lchild,k);//在左子树中递归查找elsereturn SearchBST(bt->rchild,k);//在右子树中递归查找}在二叉排序树中插入一个关键字为k的新节点,要保证插入后仍满足BST性质。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

数据结构实习报告题目:平衡二叉树的操作演示班级:信息管理与信息系统11-1姓名:崔佳学号:201101050903完成日期: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)函数之间的调用关系图:PrintTreeDeleteR_Rotate L_Rotate四、调试分析1.本程序采用了凹表输出平衡二叉树各结点的关键字的值及平衡因子的值。

相关文档
最新文档