广工数据结构实验报告平衡二叉树_第1页
广工数据结构实验报告平衡二叉树_第2页
广工数据结构实验报告平衡二叉树_第3页
广工数据结构实验报告平衡二叉树_第4页
广工数据结构实验报告平衡二叉树_第5页
已阅读5页,还剩22页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、 数据结构实验报告 题目:平衡二叉树学 院 专 业 年级班别 学 号 学生姓名 指导教师 2015年7月1日1. 题目:采用字符类型为整型类型和链式存储结构,实现抽象数据类型BTree。 ADT BTree 数据对象:Dai | aiElemSet, i=1,2,.,n, n0 数据关系:R1 |ai-1, aiD, i=2,.,n 基本操作: Adj_balance(T) 操作结果:创建平衡二叉树。 InsertAVL(T,search,taller) 初始条件:二叉树T已存在。 操作结果:增加新结点。 SetAVL(T,search,taller) 初始条件:二叉树T已存在。 操作结果:在

2、平衡二叉树上增加新结点并调平衡。 DeleteAVL(T,search,shorter) 初始条件:二叉树T已存在。 操作结果:删除结点。 ADT BTree2 存储结构定义 公用头文件DS0.h: #include #include 树的内部变量 typedefstructBTNode int data;intbf;/平衡因子structBTNode*lchild,*rchild;/左、右孩子 BTNode,*BTree; /*需要的函数声明*/ voidRight_Balance(BTree&p); voidLeft_Balance(BTree&p); voidLeft_Root_Bala

3、nce(BTree&T); voidRight_Root_Balance(BTree&T); boolInsertAVL(BTree&T,inti,bool&taller); voidPrintBT(BTreeT); voidLeft_Root_Balance_det(BTree&p,int&shorter); voidRight_Root_Balance_det(BTree&p,int&shorter); void Delete(BTree q,BTree &r,int &shorter); intDeleteAVL(BTree&p,intx,int&shorter); voidAdj_ba

4、lance(BTree&T); boolSetAVL(BTree&T,inti,bool&taller); boolInsert_Balance_AVL(BTree&T,inti,bool&taller); int menu( );3. 算法设计 /*对以*p为根的二叉排序树作右旋处理*/void Right_Balance(BTree &p) BTree lc; lc =p-lchild; /lc指向的*p左子树根结点 p-lchild = lc-rchild; /rc的右子树挂接为*p的左子树 lc-rchild = p; p = lc; /p指向新的结点/*对以*p为根的二叉排序树作左旋

5、处理*/void Left_Balance(BTree &p) BTree rc; rc = p-rchild; /指向的*p右子树根结点 p-rchild = rc-lchild; /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: /新结点插入在*T的左孩子的左

6、子树上,要作单右旋处理 T-bf = lc-bf = 0; Right_Balance(T); break; case -1: /新结点插入在*T的左孩子的右子树上,要作双旋处理 rd = lc-rchild; /rd指向*T的左孩子的右子树根 switch(rd-bf) /修改*T及其左孩子的平衡因子 case 1: T-bf = -1; lc-bf = 0; break; case 0: T-bf = lc-bf = 0; break; case -1: T-bf = 0; lc-bf = 1; break; rd-bf = 0; Left_Balance(T-lchild); /对*T的

7、左子树作左旋平衡处理 Right_Balance(T); /对*T作右旋平衡处理 /*对以指针T所指结点为根的二叉树作右平衡旋转处理*/void Right_Root_Balance(BTree &T) BTree rc,ld; rc = T-rchild; /指向*T的左子树根结点 switch(rc-bf) /检查*T的右子树的平衡度,并作相应平衡处理 case -1: /新结点插入在*T的右孩子的右子树上,要作单左旋处理 T-bf = rc-bf =0; Left_Balance(T); break; case 1: /新结点插入在*T的右孩子的左子树上,要作双旋处理 ld = rc-l

8、child; /ld指向*T的右孩子的左子树根 switch(ld-bf) /修改*T及其右孩子的平衡因子 case 1: T-bf = 0; rc-bf = -1; break; case 0: T-bf = rc-bf =0; break; case -1: T-bf = 1; rc-bf = 0; break; ld-bf = 0; Right_Balance(T-rchild);/对*T的右子树作左旋平衡处理 Left_Balance(T); /对*T作左旋平衡处理 /*插入结点i,若T中存在和i相同关键字的结点,则插入一个数据元素为i的新结点,并返回,否则返回*/bool Inser

9、tAVL(BTree &T,int i,bool &taller) if(!T)/插入新结点,树“长高”,置taller为true T = (BTree)malloc(sizeof(BTNode); T-data = i; T-lchild = T-rchild =NULL; T-bf = 0; taller = true; else if(i=T-data) /树中已存在和有相同关键字的结点 taller = 0; printf(已存在相同关键字的结点n); return 0; if(idata) /应继续在*T的左子树中进行搜索 if(!InsertAVL(T-lchild,i,talle

10、r) return 0; else /应继续在*T的右子树中进行搜索 if(!InsertAVL(T-rchild,i,taller) return 0; return 1;/*输出二叉树*/void PrintBT(BTree T) if(T) printf(%d,T-data); if(T-lchild|T-rchild) printf(); PrintBT(T-lchild); printf(,); PrintBT(T-rchild); printf(); /*删除结点时左平衡旋转处理*/void Left_Root_Balance_det(BTree &p,int &shorter)

11、BTree p1,p2; if(p-bf=1) /p结点的左子树高,删除结点后p的bf减,树变矮 p-bf=0; shorter=1; else if(p-bf=0)/p结点左、右子树等高,删除结点后p的bf减,树高不变 p-bf=-1; shorter=0; else /p结点的右子树高 p1=p-rchild;/p1指向p的右子树 if(p1-bf=0)/p1结点左、右子树等高,删除结点后p的bf为-2,进行左旋处理,树高不变 Left_Balance(p); p1-bf=1; p-bf=-1; shorter=0; else if(p1-bf=-1)/p1的右子树高,左旋处理后,树变矮

12、Left_Balance(p); p1-bf=p-bf=0; shorter=1; else /p1的左子树高,进行双旋处理(先右旋后左旋),树变矮 p2=p1-lchild; p1-lchild=p2-rchild; p2-rchild=p1; p-rchild=p2-lchild; p2-lchild=p; if(p2-bf=0) p-bf=0; p1-bf=0; else if(p2-bf=-1) p-bf=1; p1-bf=0; else p-bf=0; p1-bf=-1; p2-bf=0; p=p2; shorter=1; /*删除结点时右平衡旋转处理*/void Right_Roo

13、t_Balance_det(BTree &p,int &shorter) BTree p1,p2; if(p-bf=-1) p-bf=0; shorter=1; else if(p-bf=0) p-bf=1; shorter=0; else p1=p-lchild; if(p1-bf=0) Right_Balance(p); p1-bf=-1; p-bf=1; shorter=0; else if(p1-bf=1) Right_Balance(p); p1-bf=p-bf=0; shorter=1; else p2=p1-rchild; p1-rchild=p2-lchild; p2-lchi

14、ld=p1; p-lchild=p2-rchild; p2-rchild=p; if(p2-bf=0) p-bf=0; p1-bf=0; else if(p2-bf=1) p-bf=-1; p1-bf=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) q-data=r-data; q=r; r=r-lchild; free(q); shorter=1; else Delete(q,r-rchild,shor

15、ter); if(shorter=1) Right_Root_Balance_det(r,shorter); /*二叉树的删除操作*/int DeleteAVL(BTree &p,int x,int &shorter) int k; BTree q; if(p=NULL) printf(不存在要删除的关键字!n); return 0; else if(xdata)/在p的左子树中进行删除 k=DeleteAVL(p-lchild,x,shorter); if(shorter=1) Left_Root_Balance_det(p,shorter); return k; else if(xp-da

16、ta)/在p的右子树中进行删除 k=DeleteAVL(p-rchild,x,shorter); if(shorter=1) Right_Root_Balance_det(p,shorter); return k; else q=p; if(p-rchild=NULL) /右子树空则只需重接它的左子树 p=p-lchild; free(q); shorter=1; else if(p-lchild=NULL)/左子树空则只需重接它的右子树 p=p-rchild; free(q); shorter=1; else/左右子树均不空 Delete(q,q-lchild,shorter); if(sh

17、orter=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 = i; T-lchild = T-rchild =NULL; T-bf = 0; taller = true; else if(i=T-data) /树中已存在和有相同关键字的结点 taller = false; printf(

18、已存在相同关键字的结点n); return 0; if(idata) /应继续在*T的左子树中进行搜索 if(!SetAVL(T-lchild,i,taller) return 0; if(taller) /已插入到*T的左子树中且左子树“长高” switch(T-bf) /检查*T的平衡度 case 1: /原本左子树比右子树高,需要作左平衡处理 Left_Root_Balance(T); taller = false; break; case 0: /原本左子树、右子等高,现因左子树增高而使树增高 T-bf = 1; taller = true; break; case -1: /原本右子

19、树比左子树高,现左、右子树等高 T-bf = 0; taller = false; break; else /应继续在*T的右子树中进行搜索 if(!SetAVL(T-rchild,i,taller) return 0; if(taller) /已插入到*T的右子树中且右子树“长高” switch(T-bf) /检查*T的平衡度 case 1: /原本左子树比右子树高,现左、右子树等高 T-bf = 0; taller = false; break; case 0: /原本左子树、右子等高,现因右子树增高而使树增高 T-bf = -1; taller = true; break; case -

20、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); getchar(); while(i != -1) SetAVL(T,i,taller); printf(n请输入关键字(以-1结束建立平衡二叉树):); scanf(%d,&i); getchar(

21、); 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); printf( 2 在平衡二叉树上增加新结点并调衡n); printf( 3 在平衡二叉树上删除一个结点并调衡n); printf( 0 退出n); printf( _nn); printf( 请输入所选功能0-3n); scanf(%

22、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( ); switch(input) case 1: Adj_balance(T); break; case 2: printf(请输入你要增加的关键字); scanf(%d,&search); getchar(); SetAVL(T,sea

23、rch,taller); PrintBT(T); break; case 3: printf(请输入你要删除的关键字); scanf(%d,&search); getchar(); DeleteAVL(T,search,shorter); PrintBT(T); break; case 0: break; default: printf(输入错误,请重新选择。); break; if(input = 0) break; printf(按任意键继续.); getchar(); 测试截图:1. 界面:2. 创建平衡二叉树:3.增加节点并调衡:4.删除节点并调衡:5. 思考与小结在平衡二叉树中任何节

24、点的两个子树的高度最大差别为1,所以它也被称为高度平衡树。查找、插入和删除在平均和最坏情况下都是O(log n)。增加和删除可能需要通过一次或多次树旋转来重新平衡这个树。平衡二叉树是在构造二叉排序树的过程中,每当插入一个新结点时,首先检查是否因插入新结点而破坏了二叉排序树的平衡性,若是,则找出其中的最小不平衡子树,在保持二叉排序树特性的前提下,调整最小不平衡子树中各结点之间的链接关系,进行相应的旋转,使之成为新的平衡子树。6. 源代码#include#include typedef struct BTNode int data; int bf; /平衡因子 struct BTNode *lch

25、ild,*rchild;/左、右孩子BTNode,*BTree;/*对以*p为根的二叉排序树作右旋处理*/void Right_Balance(BTree &p) BTree lc; lc =p-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;

26、/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: /新结点插入在*T的左孩子的左子树上,要作单右旋处理 T-bf = lc-bf = 0; Right_Balance(T); break; case -1: /新结点插入在*T的左孩子的右子树上,要作双旋处理 rd

27、 = lc-rchild; /rd指向*T的左孩子的右子树根 switch(rd-bf) /修改*T及其左孩子的平衡因子 case 1: T-bf = -1; lc-bf = 0; break; case 0: T-bf = lc-bf = 0; break; case -1: T-bf = 0; lc-bf = 1; break; rd-bf = 0; Left_Balance(T-lchild); /对*T的左子树作左旋平衡处理 Right_Balance(T); /对*T作右旋平衡处理 /*对以指针T所指结点为根的二叉树作右平衡旋转处理*/void Right_Root_Balance(

28、BTree &T) BTree rc,ld; rc = T-rchild; /指向*T的左子树根结点 switch(rc-bf) /检查*T的右子树的平衡度,并作相应平衡处理 case -1: /新结点插入在*T的右孩子的右子树上,要作单左旋处理 T-bf = rc-bf =0; Left_Balance(T); break; case 1: /新结点插入在*T的右孩子的左子树上,要作双旋处理 ld = rc-lchild; /ld指向*T的右孩子的左子树根 switch(ld-bf) /修改*T及其右孩子的平衡因子 case 1: T-bf = 0; rc-bf = -1; break; c

29、ase 0: T-bf = rc-bf =0; break; case -1: T-bf = 1; rc-bf = 0; break; ld-bf = 0; Right_Balance(T-rchild);/对*T的右子树作左旋平衡处理 Left_Balance(T); /对*T作左旋平衡处理 /*插入结点i,若T中存在和i相同关键字的结点,则插入一个数据元素为i的新结点,并返回,否则返回*/bool InsertAVL(BTree &T,int i,bool &taller) if(!T)/插入新结点,树“长高”,置taller为true T = (BTree)malloc(sizeof(B

30、TNode); T-data = i; T-lchild = T-rchild =NULL; T-bf = 0; taller = 1; else if(i=T-data) /树中已存在和有相同关键字的结点 taller = 0; printf(已存在相同关键字的结点n); return 0; if(idata) /应继续在*T的左子树中进行搜索 if(!InsertAVL(T-lchild,i,taller) return 0; else /应继续在*T的右子树中进行搜索 if(!InsertAVL(T-rchild,i,taller) return 0; return 1;/*输出平衡二叉

31、树*/void PrintBT(BTree T) if(T) printf(%d,T-data); if(T-lchild|T-rchild) printf(); PrintBT(T-lchild); printf(,); PrintBT(T-rchild); printf(); /*删除结点时左平衡旋转处理*/void Left_Root_Balance_det(BTree &p,int &shorter) BTree p1,p2; if(p-bf=1) /p结点的左子树高,删除结点后p的bf减,树变矮 p-bf=0; shorter=1; else if(p-bf=0)/p结点左、右子树等

32、高,删除结点后p的bf减,树高不变 p-bf=-1; shorter=0; else /p结点的右子树高 p1=p-rchild;/p1指向p的右子树 if(p1-bf=0)/p1结点左、右子树等高,删除结点后p的bf为-2,进行左旋处理,树高不变 Left_Balance(p); p1-bf=1; p-bf=-1; shorter=0; else if(p1-bf=-1)/p1的右子树高,左旋处理后,树变矮 Left_Balance(p); p1-bf=p-bf=0; shorter=1; else /p1的左子树高,进行双旋处理(先右旋后左旋),树变矮 p2=p1-lchild; p1-lchild=p2-rchild; p2-rchild=p1; p-rchild=p2-lchild; p2-lchild=p; if(p2-bf=0) p-bf=0; p1-bf=0; else if(p2-bf=-1) p-bf=1; p1-bf=0; el

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论