1、广工数据结构实验报告平衡二叉树 数据结构实验报告 题目:平衡二叉树学 院 专 业 年级班别 学 号 学生姓名 指导教师 2015年7月1日1.题目:采用字符类型为整型类型和链式存储结构,实现抽象数据类型BTree。 ADT BTree 数据对象:Dai | aiElemSet, i=1,2,。.。,n, n0 数据关系:R1 ai1, aiD, i=2,。.,n 基本操作: Adj_balance(T) 操作结果:创建平衡二叉树。 InsertAVL(T,search,taller) 初始条件:二叉树T已存在。 操作结果:增加新结点。 SetAVL(T,search,taller) 初始条件:
2、二叉树T已存在。 操作结果:在平衡二叉树上增加新结点并调平衡. DeleteAVL(T,search,shorter) 初始条件:二叉树T已存在. 操作结果:删除结点。 ADT BTree2存储结构定义 公用头文件DS0。h: #includestdio。h #include malloc.h 树的内部变量 typedefstructBTNode int data;intbf;/平衡因子structBTNodelchild,rchild;/左、右孩子 BTNode,*BTree; /*需要的函数声明/ voidRight_Balance(BTreep); voidLeft_Balance(BT
3、ree&p); voidLeft_Root_Balance(BTreeT); voidRight_Root_Balance(BTreeT); boolInsertAVL(BTree&T,inti,bool&taller); voidPrintBT(BTreeT); voidLeft_Root_Balance_det(BTree&p,int&shorter); voidRight_Root_Balance_det(BTreep,int&shorter); void Delete(BTree q,BTree &r,int shorter); intDeleteAVL(BTreep,intx,int
4、&shorter); voidAdj_balance(BTreeT); boolSetAVL(BTree&T,inti,booltaller); boolInsert_Balance_AVL(BTree&T,inti,booltaller); int menu( );3. 算法设计 /对以p为根的二叉排序树作右旋处理*/void Right_Balance(BTree &p) BTree lc; lc =p-lchild; /lc指向的p左子树根结点 p-lchild = lc-rchild; /rc的右子树挂接为p的左子树 lcrchild = p; p = lc; /p指向新的结点/*对以
5、p为根的二叉排序树作左旋处理*/void Left_Balance(BTree p) BTree rc; rc = p-rchild; /指向的*p右子树根结点 prchild = rclchild; /rc左子树挂接到p的右子树 rc-lchild = p; p = rc; /p指向新的结点/*对以指针T所指结点为根的二叉树作左平衡旋转处理*/void Left_Root_Balance(BTree &T) BTree lc,rd; lc = T-lchild; /指向*T的左子树根结点 switch(lc-bf) /检查*T的左子树的平衡度,并作相应平衡处理 case 1: /新结点插入在
6、*T的左孩子的左子树上,要作单右旋处理 Tbf = lcbf = 0; Right_Balance(T); break; case -1: /新结点插入在*T的左孩子的右子树上,要作双旋处理 rd = lcrchild; /rd指向T的左孩子的右子树根 switch(rd-bf) /修改*T及其左孩子的平衡因子 case 1: T-bf = -1; lcbf = 0; break; case 0: T-bf = lcbf = 0; break; case 1: T-bf = 0; lcbf = 1; break; rdbf = 0; Left_Balance(T-lchild); /对T的左子
7、树作左旋平衡处理 Right_Balance(T); /对T作右旋平衡处理 /对以指针T所指结点为根的二叉树作右平衡旋转处理*/void Right_Root_Balance(BTree &T) BTree rc,ld; rc = Trchild; /指向*T的左子树根结点 switch(rcbf) /检查*T的右子树的平衡度,并作相应平衡处理 case -1: /新结点插入在T的右孩子的右子树上,要作单左旋处理 T-bf = rc-bf =0; Left_Balance(T); break; case 1: /新结点插入在*T的右孩子的左子树上,要作双旋处理 ld = rclchild; /
8、ld指向T的右孩子的左子树根 switch(ldbf) /修改T及其右孩子的平衡因子 case 1: T-bf = 0; rcbf = -1; break; case 0: Tbf = rc-bf =0; break; case -1: Tbf = 1; rcbf = 0; break; ldbf = 0; Right_Balance(T-rchild);/对*T的右子树作左旋平衡处理 Left_Balance(T); /对T作左旋平衡处理 /*插入结点i,若T中存在和i相同关键字的结点,则插入一个数据元素为i的新结点,并返回,否则返回*/bool InsertAVL(BTree T,int
9、i,bool &taller) if(!T)/插入新结点,树“长高”,置taller为true T = (BTree)malloc(sizeof(BTNode); T-data = i; Tlchild = Trchild =NULL; T-bf = 0; taller = true; else if(i=Tdata) /树中已存在和有相同关键字的结点 taller = 0; printf(已存在相同关键字的结点n”); return 0; if(iTdata) /应继续在T的左子树中进行搜索 if(!InsertAVL(T-lchild,i,taller) return 0; else /应
10、继续在T的右子树中进行搜索 if(!InsertAVL(Trchild,i,taller) return 0; return 1;/*输出二叉树/void PrintBT(BTree T) if(T) printf(”%d,T-data); if(T-lchild|T-rchild) printf(); PrintBT(Tlchild); printf(,”); PrintBT(T-rchild); printf(”)”); /*删除结点时左平衡旋转处理*/void Left_Root_Balance_det(BTree &p,int &shorter) BTree p1,p2; if(p-b
11、f=1) /p结点的左子树高,删除结点后p的bf减,树变矮 pbf=0; shorter=1; else if(p-bf=0)/p结点左、右子树等高,删除结点后p的bf减,树高不变 p-bf=1; shorter=0; else /p结点的右子树高 p1=prchild;/p1指向p的右子树 if(p1bf=0)/p1结点左、右子树等高,删除结点后p的bf为2,进行左旋处理,树高不变 Left_Balance(p); p1bf=1; p-bf=-1; shorter=0; else if(p1-bf=-1)/p1的右子树高,左旋处理后,树变矮 Left_Balance(p); p1bf=pbf
12、=0; shorter=1; else /p1的左子树高,进行双旋处理(先右旋后左旋),树变矮 p2=p1lchild; p1lchild=p2rchild; p2rchild=p1; prchild=p2-lchild; p2lchild=p; if(p2bf=0) p-bf=0; p1bf=0; else if(p2-bf=1) p-bf=1; p1bf=0; else p-bf=0; p1bf=1; p2-bf=0; p=p2; shorter=1; /删除结点时右平衡旋转处理*/void Right_Root_Balance_det(BTree p,int shorter) BTree
13、 p1,p2; if(p-bf=-1) p-bf=0; shorter=1; else if(p-bf=0) pbf=1; shorter=0; else p1=p-lchild; if(p1bf=0) Right_Balance(p); p1bf=1; pbf=1; shorter=0; else if(p1-bf=1) Right_Balance(p); p1-bf=pbf=0; shorter=1; else p2=p1rchild; p1rchild=p2lchild; p2-lchild=p1; p-lchild=p2rchild; p2-rchild=p; if(p2-bf=0)
14、pbf=0; p1-bf=0; else if(p2-bf=1) pbf=1; p1bf=0; else p-bf=0; p1-bf=1; p2-bf=0; p=p2; shorter=1; /删除结点*/void Delete(BTree q,BTree r,int shorter) if(r-rchild=NULL) qdata=r-data; q=r; r=rlchild; free(q); shorter=1; else Delete(q,rrchild,shorter); if(shorter=1) Right_Root_Balance_det(r,shorter); /*二叉树的删
15、除操作/int DeleteAVL(BTree &p,int x,int shorter) int k; BTree q; if(p=NULL) printf(不存在要删除的关键字!n); return 0; else if(xp-data)/在p的右子树中进行删除 k=DeleteAVL(prchild,x,shorter); if(shorter=1) Right_Root_Balance_det(p,shorter); return k; else q=p; if(p-rchild=NULL) /右子树空则只需重接它的左子树 p=plchild; free(q); shorter=1;
16、else if(p-lchild=NULL)/左子树空则只需重接它的右子树 p=prchild; free(q); shorter=1; else/左右子树均不空 Delete(q,q-lchild,shorter); if(shorter=1) Left_Root_Balance_det(p,shorter); p=q; return 1; /*调平二叉树具体方法/bool SetAVL(BTree T,int i,bool &taller) if(!T)/插入新结点,树“长高”,置taller为true T = (BTree)malloc(sizeof(BTNode); T-data =
17、i; Tlchild = Trchild =NULL; Tbf = 0; taller = true; else if(i=T-data) /树中已存在和有相同关键字的结点 taller = false; printf(已存在相同关键字的结点n”); return 0; if(iTdata) /应继续在*T的左子树中进行搜索 if(!SetAVL(T-lchild,i,taller) return 0; if(taller) /已插入到T的左子树中且左子树“长高” switch(Tbf) /检查T的平衡度 case 1: /原本左子树比右子树高,需要作左平衡处理 Left_Root_Balan
18、ce(T); taller = false; break; case 0: /原本左子树、右子等高,现因左子树增高而使树增高 T-bf = 1; taller = true; break; case -1: /原本右子树比左子树高,现左、右子树等高 Tbf = 0; taller = false; break; else /应继续在*T的右子树中进行搜索 if(!SetAVL(Trchild,i,taller) return 0; if(taller) /已插入到T的右子树中且右子树“长高” switch(T-bf) /检查T的平衡度 case 1: /原本左子树比右子树高,现左、右子树等高
19、T-bf = 0; taller = false; break; case 0: /原本左子树、右子等高,现因右子树增高而使树增高 T-bf = -1; taller = true; break; case 1: /原本右子树比左子树高,需要作右平衡处理 Right_Root_Balance(T); taller = false; break; return 1; /二叉树调平操作*/void Adj_balance(BTree T) int i; bool taller=false; T = NULL; printf(”n请输入关键字(以1结束建立平衡二叉树):); scanf(%d,i);
20、 getchar(); while(i != -1) SetAVL(T,i,taller); printf(n请输入关键字(以-1结束建立平衡二叉树):”); scanf(”d,i); getchar(); taller=false; printf(平衡二叉树创建结束。n); if(T) PrintBT(T); else printf(这是一棵空树。n); /菜单函数/ int menu( ) int m; printf(.。.。.。.。.2015年7月1日.。.。.。.。.nn); printf( 平衡二叉树n); printf(” _nn); printf(” 1 创建平衡二叉树n); p
21、rintf( 2 在平衡二叉树上增加新结点并调衡n); printf(” 3 在平衡二叉树上删除一个结点并调衡n); printf(” 0 退出n”); printf( _nn); printf( 请输入所选功能03n); scanf(”%d,m); return m; 4测试/主函数/void main() int input,search; bool taller=0; int shorter=0; BTree T; T=(BTree)malloc(sizeof(BTNode); T=NULL; while(1) printf(n请选择需要的二叉树操作n); input=menu( );
22、switch(input) case 1: Adj_balance(T); break; case 2: printf(”请输入你要增加的关键字”); scanf(”%d”,&search); getchar(); SetAVL(T,search,taller); PrintBT(T); break; case 3: printf(请输入你要删除的关键字”); scanf(”d”,&search); getchar(); DeleteAVL(T,search,shorter); PrintBT(T); break; case 0: break; default: printf(”输入错误,请重
23、新选择。”); break; if(input = 0) break; printf(”按任意键继续.); getchar(); 测试截图:1.界面:2.创建平衡二叉树:3.增加节点并调衡:4。删除节点并调衡:5. 思考与小结在平衡二叉树中任何节点的两个子树的高度最大差别为1,所以它也被称为高度平衡树.查找、插入和删除在平均和最坏情况下都是O(log n)。增加和删除可能需要通过一次或多次树旋转来重新平衡这个树。平衡二叉树是在构造二叉排序树的过程中,每当插入一个新结点时,首先检查是否因插入新结点而破坏了二叉排序树的平衡性,若是,则找出其中的最小不平衡子树,在保持二叉排序树特性的前提下,调整最小
24、不平衡子树中各结点之间的链接关系,进行相应的旋转,使之成为新的平衡子树。6. 源代码#includestdio.hinclude lchild; /lc指向的*p左子树根结点 p-lchild = lc-rchild; /rc的右子树挂接为*p的左子树 lc-rchild = p; p = lc; /p指向新的结点/*对以p为根的二叉排序树作左旋处理/void Left_Balance(BTree p) BTree rc; rc = p-rchild; /指向的p右子树根结点 p-rchild = rc-lchild; /rc左子树挂接到p的右子树 rclchild = p; p = rc;
25、/p指向新的结点/对以指针T所指结点为根的二叉树作左平衡旋转处理*/void Left_Root_Balance(BTree T) BTree lc,rd; lc = T-lchild; /指向T的左子树根结点 switch(lc-bf) /检查T的左子树的平衡度,并作相应平衡处理 case 1: /新结点插入在T的左孩子的左子树上,要作单右旋处理 T-bf = lcbf = 0; Right_Balance(T); break; case -1: /新结点插入在T的左孩子的右子树上,要作双旋处理 rd = lc-rchild; /rd指向T的左孩子的右子树根 switch(rdbf) /修改*T及其左孩子的平衡因子 case 1: Tbf = 1; lc-bf = 0; break; case 0: T-bf = lcbf =
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1