平衡二叉树关于树的深度是平衡的,具有较高的检索效率。平衡二叉树或是一棵空树,或是具有下列性质的二叉排序树:其左子树和右子树都是平衡二叉树,而且左右子树深度之差绝对值不超过1. 由此引出了平衡因子(balance factor)的概念,bf定义为该结点的左子树的深度减去右子树的深度(有些书是右子树深度减去左子树深度,我是按照左子树减去右子树来计算的,下面的代码也是这样定义的),所以平衡二叉树的结点的平衡因子只可能是-1,0,1 ,某个结点的平衡因子绝对值大于1,该二叉树就不平衡。
平衡二叉树在出现不平衡状态的时候,要进行平衡旋转处理,有四种平衡旋转处理(单向右旋处理,单向左旋处理,双向旋转(先左后右)处理,双向旋转(先右后左)处理),归根到底是两种(单向左旋处理和单向右旋处理)。
文件"tree.h"
view plain
1.#include
2.#include
3.#include
https://www.wendangku.net/doc/d67952868.html,ing namespace std;
5.
6.const int LH=1; //左子树比右子树高1
7.const int EH=0; //左右子树一样高
8.const int RH=-1;//右子树比左子树高1
9.const int MAX_NODE_NUM=20; //结点数目上限
10.
11.class AVL_Tree;
12.
13.class AvlNode
14.{
15.int data;
16.int bf; //平衡因子
17. AvlNode *lchild;
18. AvlNode *rchild;
19.friend class AVL_Tree;
20.};
21.
22.class AVL_Tree
23.{
24.public:
25.int Get_data(AvlNode *p)
26. {
27.return p->data;
28. }
29.
30.void Create_AVl(AvlNode *&T) //建树
31. {
32. cout<<"输入平衡二叉树的元素,输入-1代表结束输入:";
33.int num[MAX_NODE_NUM];
34.int a,i=0;
35.while(cin>>a && a!=-1)
36. {
37. num[i]=a;
38. i++;
39. }
40.
41.if(num[0]==-1)
42. {
43. cout<<"平衡树为空"< 44. T=NULL; 45.return; 46. } 47. 48.int k=i; 49.bool taller=false; 50.for(i=0;i 51. Insert_Avl(T,num[i],taller);//逐个进行插入,插入过程看下面的示意图 52. cout<<"_____建树完成____"< 53. } 54. 55.void L_Rotate(AvlNode *&p) 56. { 57.//以p为根节点的二叉排序树进行单向左旋处理 58. AvlNode *rc=p->rchild; 59. p->rchild=rc->lchild; 60. rc->lchild=p; 61. p=rc; 62. } 63. 64.void R_Rotate(AvlNode *&p) 65. { 66.//以p为根节点的二叉排序树进行单向右旋处理 67. AvlNode *lc=p->lchild; 68. p->lchild=lc->rchild; 69. lc->rchild=p; 70. p=lc; 71. } 72. 73.void Left_Balance(AvlNode *&T) 74. { 75.//以T为根节点的二叉排序树进行左平衡旋转处理 76. AvlNode *lc,*rd; 77. lc=T->lchild; 78.switch(lc->bf) 79. { 80.case LH: 81.//新结点插在T的左孩子的左子树上,做单向右旋处理 82. T->bf=lc->bf=EH; 83. R_Rotate(T); 84.break; 85.case RH: 86.//新结点插在T的左孩子的右子树上,要进行双旋平衡处理(先左后右) 87. rd=lc->rchild; 88.switch(rd->bf) 89. { 90.case LH: 91.//插在右子树的左孩子上 92. T->bf=RH; 93. lc->bf=EH; 94.break; 95.case EH: 96. T->bf=lc->bf=EH; 97.break; 98.case RH: 99. T->bf=EH; 100. lc->bf=LH; 101.break; 102. } 103. rd->bf=EH; 104. L_Rotate(T->lchild);//先对T的左子树进行单向左旋处理 105. R_Rotate(T); //再对T进行单向右旋处理 106. } 107. } 108. 109.void Right_Balance(AvlNode *&T) 110. { 111.//以T为根节点的二叉排序树进行右平衡旋转处理 112. AvlNode *rc,*ld; 113. rc=T->rchild; 114.switch(rc->bf) 115. { 116.case RH: 117.//新结点插在右孩子的右子树上,进行单向左旋处理 118. T->bf=rc->bf=EH; 119. L_Rotate(T); 120.break; 121.case LH: 122.//新结点插在T的右孩子的左子树上,要进行右平衡旋转处理(先右再左)123. ld=rc->lchild; 124.switch(ld->bf) 125. { 126.case LH: 127. T->bf=LH; 128. rc->bf=EH; 129.break; 130.case EH: 131. T->bf=rc->bf=EH; 132.break; 133.case RH: 134. T->bf=EH; 135. rc->bf=RH; 136.break; 137. } 138. ld->bf=EH; 139. R_Rotate(T->rchild);//先对T的右子树进行单向右旋处理 140. L_Rotate(T); //再对T进行单向左旋处理 141. } 142. } 143. 144.bool Insert_Avl(AvlNode *&T,int num,bool &taller) //插入 145. { 146.//若在平衡二叉树中不存在结点值和num一样大小的结点 147.//则插入值为num的新结点,并返回true 148.//若因为插入而使得二叉排序树失去平衡,则做平衡旋转处理 149.//taller反映树是否长高 150. 151.if(!T) 152. { 153.//插入新结点,树长高,taller为true 154. T=new AvlNode; 155. T->data=num; 156. T->lchild=T->rchild=NULL; 157. T->bf=EH; 158. taller=true; 159. } 161. { 162.if(num==T->data) 163. { 164.//不重复插入 165. taller=false; 166.return false; 167. } 168.if(num 169. { 170.if(!Insert_Avl(T->lchild,num,taller))//插入不成功 171.return false; 172.if(taller) //已插入T的左子树,且左子树长高 173. { 174.switch(T->bf) 175. { 176.case LH: 177./*————————————————————— 178. / 插入前左子树高于右子树,需要进行做平衡处理 179. / 不管是单向左旋处理,还是先左后右平衡处理 180. / 处理结果都是使得插入新结点后,树的高度不变 181. /—————————————————————*/ 182. 183. Left_Balance(T); 184. taller=false; 185.break; 186.case EH: 187.//插入前左右子树等高,现在插入新街点后,左子树比右子树高188. 189. T->bf=LH; 190. taller=true; 191.break; 192.case RH: 193.//插入前右子树比左子树高,现在新结点插入左子树后,树变为左右子树等高 194. 195. T->bf=EH; 196. taller=false; 197.break; 198. 199. } 200. } 201. } 202.else 204.//num>T->data 在T的右子树中继续搜索 205.if(!Insert_Avl(T->rchild,num,taller)) 206.return false; 207.if(taller) 208. { 209.switch(T->bf) 210. { 211.case LH: 212.//插入前左子树比右子树高,现在插入T的右子树后,左右子树等高 213. 214. T->bf=EH; 215. taller=false; 216.break; 217.case EH: 218.//插入前左右子树等高,现在插入后,右子树比左子树高219. 220. T->bf=RH; 221. taller=true; 222.break; 223. 224.case RH: 225.//插入前右子树比坐子树高,插入后,排序树失去平衡,需要进行右平衡处理 226. Right_Balance(T); 227. taller=false; 228.break; 229. 230. } 231. } 232. } 233. } 234.return true; 235. } 236. 237.bool Search_Avl(AvlNode *T,int num,AvlNode *&f,AvlNode *&p) //搜索238. { 239.//用p带回查找到的顶点的地址,f带回p的双亲结点 240. p=T; 241.while(p) 242. { 243.if(p->data==num) 244.return true; 245.if(p->data>num) 246. { 247. f=p; 248. p=p->lchild; 249. } 250.else 251. { 252. f=p; 253. p=p->rchild; 254. } 255. } 256.return false; 257. } 258. 259.void Delete_AVL(AvlNode *&T,int num) //删除 260. { 261./*---------------------------------------------------------262. / 从树中删除一个节点后,要保证删后的树还是一棵平衡二叉树, 263. / 删除前,首先是在树中查找是否有这个结点,用p指向该结点, 264. / 用f指向p的双亲结点,这个结点在树中的位置有下面四种情况: 265. / 266. / 1:如果p指向的结点是叶子结点,那么直接将f指针的左子树或者267. / 右子树置空,然后删除p结点即可。 268. / 269. / 2:如果p指向的结点是只有左子树或右子树,那么只需要让p结点270. / 原来在f中的位置(左子树或右子树)用p的子树代替即可。 271. / 代替后,要修改f的平衡因子,在失去平衡的时候,要调用相应的272. / 做平衡旋转或右平衡旋转进行恢复. 273. / 274. / 3:如果p所指向的结点是根节点,那么直接将根节点置空 275. / 276. / 4:如果p所指向的结点左右子树都非空,为了删除p后原序列的顺277. / 序不变,就需要在原序列中先找出p的直接前驱(或者直接后继) 278. / 结点用那个结点的值来代替p结点的值,然后再删掉那个直接前 279. / 驱(或者直接后继)结点。 280. / 其中s指向的是要删除的结点,也就是p的直接前驱,q指向的是281. / s的双亲结点,此时,应该看s的平衡因子,在会出现失去平衡的282. / 情况时,就要根据实际情况采用左平衡旋转或是右平衡旋转,让 283. / 树恢复平衡,这点和插入操作时是相对应的。 284. / 285. / 在中序遍历序列中找结点的直接前驱的方法是顺着结点的左孩子 286. / 的右链域开始,一直到结点右孩子为空为止。 287. /---------------------------------------------------------*/ 288. 289. AvlNode *f=NULL; 290. AvlNode *p=NULL; 291. AvlNode *q=NULL; 292. AvlNode *s=NULL; 293.if(Search_Avl(T,num,f,p)) 294. { 295.if(p->lchild && p->rchild) //左右子树均存在时 296. { 297. q=p; 298. s=p->lchild; 299.while(s->rchild) 300. { 301. q=s; 302. s=s->rchild; 303. } 304. p->data=s->data; 305.if(q!=p) 306. { 307.//q结点的右子树高度减少1 308.//所以平衡因子会+1 309. q->rchild=s->lchild; 310.switch(q->bf) 311. { 312.//删除前右子树高,现在就变成一样高 313.case RH: 314. q->bf=EH; break; 315.//删除前等高,现在就变成左子树比右子树高 316.case EH: 317. q->bf=LH; break; 318.//删除前左子树高,现在左子树又高了一,所以失去平衡319.case LH: 320. q->bf=EH; 321. Left_Balance(q); 322.break; 323. } 324. } 325.else 326. { 327.//p的左子树的右子树为空时 328.//q结点也就是p结点,由于s的右子树为空 329.//所以q结点的左子树高度降低1 330.//平衡因子-1 331. q->lchild=s->lchild; 332.switch(q->bf) 333. { 334.case LH: 335. q->bf=EH;break; 336.case EH: 337. q->bf=RH;break; 338.case RH: 339. q->bf=EH; 340. Right_Balance(q); 341.break; 342. } 343. } 344.delete s; 345. cout<<"删除结点成功"< 347. } 348.else 349. { 350.if(!p->lchild) 351. { 352. q=p; 353. p=p->rchild; 354. } 355.else 356. { 357. q=p; 358. p=p->lchild; 359. } 360.if(!T) 361. { 362. T->bf=EH; 363. T=p; 364. } 365.else if(q==f->lchild) 366. { 367. f->lchild=p; 368.switch(f->bf) 369. { 370.case LH: 371. f->bf=EH; break; 372.case EH: 373. f->bf=RH; break; 374.case RH: 375. f->bf=EH; 376. Right_Balance(f); 377.break; 378. } 379. } 380.else 381. { 382. f->rchild=p; 383.switch(f->bf) 384. { 385.case RH: 386. f->bf=EH; break; 387.case EH: 388. f->bf=LH; break; 389.case LH: 390. f->bf=EH; 391. Left_Balance(f); 392.break; 393. } 394. } 395.delete q; 396. cout<<"删除结点成功"< 398. } 399. } 400.else 401. { 402. cout<<"要删除的结点不存在"< 404. } 405. } 406. 407. InOrder_Traverse(AvlNode *T) //中序遍历408. { 409. stack 410. AvlNode *p=T; 411. 412.while(p || !s.empty()) 413. { 414.if(p) 415. { 416. s.push(p); 417. p=p->lchild; 418. } 419.else 420. { 421. p=s.top(); 422. s.pop(); 423. cout< 424. p=p->rchild; 425. } 426. } 427. } 428. 429.void Level_Traverse(AvlNode *T) //层次遍历430. { 431. queue 432. AvlNode *p=T; 433. q.push(p); 434.while(!q.empty()) 435. { 436. p=q.front(); 437. q.pop(); 438. cout< 439.if(p->lchild) 440. q.push(p->lchild); 441.if(p->rchild) 442. q.push(p->rchild); 443. } 444. } 445. 446.}; 测试文件"main.cpp" view plain 1.#include"tree.h" 2. 3.int main() 4.{ 5. AVL_Tree tree; 6. AvlNode *root=NULL; 7. cout<<"____建立平衡二叉树____"< 8. tree.Create_AVl(root); 9. 10. cout<<"中序遍历二叉树为:"; 11. tree.InOrder_Traverse(root); 12. cout< 13. 14. cout<<"层次遍历二叉树为:"; 15. tree.Level_Traverse(root); 16. cout< 17. 18.int num; 19.bool taller=false; 20. cout<<"输入你要插入的结点的值:"; 21. cin>>num; 22. tree.Insert_Avl(root,num,taller); 23. 24. cout<<"中序遍历二叉树为:"; 25. tree.InOrder_Traverse(root); 26. cout< 27. 28. AvlNode *f=NULL; 29. AvlNode *p=NULL; 30. cout<<"输入你要搜索的结点的值:"; 31. cin>>num; 32.if(tree.Search_Avl(root,num,f,p)) 33. { 34. cout<<"查找得到的结点值为:"< 35.if(f==NULL) 36. cout<<"因为结点"< "< 37.else 38. cout<<"该结点的双亲结点的值为:"< 39. } 40.else 41. cout<<"查找的结点不存在"< 42. 43. cout<<"输入你要删除的结点的值:"; 44. cin>>num; 45. tree.Delete_AVL(root,num); 46. 47. cout<<"中序遍历二叉树为:"; 48. tree.InOrder_Traverse(root); 49. cout< 50. 51.return 0; 52.} 测试结果 view plain 1.____建立平衡二叉树____ 2.输入平衡二叉树的元素,输入-1代表结束输入:16 3 7 11 9 26 18 14 15 -1 3._____建树完成____ 4.中序遍历二叉树为:3 7 9 11 14 15 16 18 26 5.层次遍历二叉树为:11 7 18 3 9 15 26 14 16 6.输入你要插入的结点的值:20 7.中序遍历二叉树为:3 7 9 11 14 15 16 18 20 26 8.输入你要搜索的结点的值:20 9.查找得到的结点值为:20的地址为:00380BB0 10.该结点的双亲结点的值为:26 11.输入你要删除的结点的值:15 12.删除结点成功 13.中序遍历二叉树为:3 7 9 11 14 16 18 20 26 14.Press any key to continue 下面是四种旋转的示意图 先右后左的和先左后右的相对应的所以不画了下面再画一个建树的过程就不画了太费时间了画这个刚好找到一个画好的直接贴 因为下面图中它的计算平衡因子的方式是右子树高度减去左子树高度,所以和我上面的计算方法相反,不过不影响观看 建立含有元素16 3 7 11 9 26 18 14 15 的平衡二叉树的过程如下所示: 平衡二叉树操作的演示 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{ 二叉排序树变成平衡二叉树 对于二叉查找树,尽管查找、插入及删除操作的平均运行时间为O(logn),但是它们的最差运行时间都是O(n),原因在于对树的形状没有限制。 平衡二叉树又称为AVL树,它或者是一棵空树,或者是有下列性质的二叉树:它的左子树和右子树都是平衡二叉树,且左右子树的深度之差的绝对值不超过1。二叉树的的平衡因子BF为:该结点的左子树的深度减去它的右子树的深度,则平衡二叉树的所有结点的平衡因子为只可能是:-1、0和1 一棵好的平衡二叉树的特征: (1)保证有n个结点的树的高度为O(logn) (2)容易维护,也就是说,在做数据项的插入或删除操作时,为平衡树所做的一些辅助操作时间开销为O(1) 一、平衡二叉树的构造 在一棵二叉查找树中插入结点后,调整其为平衡二叉树。若向平衡二叉树中插入一个新结点后破坏了平衡二叉树的平衡性。首先要找出插入新结点后失去平衡的最小子树根结点的指针。然后再调整这个子树中有关结点之间的链接关系,使之成为新的平衡子树。当失去平衡的最小子树被调整为平衡子树后,原有其他所有不平衡子树无需调整,整个二叉排序树就又成为一棵平衡二叉树 1.调整方法 (1)插入点位置必须满足二叉查找树的性质,即任意一棵子树的左结点都小于根结点,右结点大于根结点 (2)找出插入结点后不平衡的最小二叉树进行调整,如果是整个树不平衡,才进行整个树的调整。 2.调整方式 (1)LL型 LL型:插入位置为左子树的左结点,进行向右旋转(LL表示的是在做子树的左结点进行插入) 由于在A的左孩子B的左子树上插入结点F,使A的平衡因子由1变为2,成为不平衡的最小二叉树根结点。此时A结点顺时针右旋转,旋转过程中遵循“旋转优先”的规则,A结点替换D结点成为B结点的右子树,D结点成为A结点的左孩子。 (2)RR型 计算机科学学院数据结构课程设计报告 平衡二叉树操作 学生姓名: 学号: 班级: 指导老师: 报告日期: 1.需求分析 1.建立平衡二叉树并进行创建、查找、插入、删除等功能。 2.设计一个实现平衡二叉树的程序,可进行创建、查找、插入、删除等操作,实现动态的输入数据,实时的输出该树结构。 3.测试数据:自选数据 2.概要设计 1.抽象数据类型定义: typedef struct BSTNode { int data; int bf; //节点的平衡因子 struct BSTNode *lchild,*rchild; //左右孩子指针 }BSTNode,*BSTree; void CreatBST(BSTree &T); //创建平衡二叉树 void R_Rotate(BSTree &p); //对以*p为根的二叉排序树作左旋处理 void L_Rotate(BSTree &p); //对以*p为根的二叉排序树作左旋处理 void LeftBalance(BSTree &T); //对以指针T所指结点为根的二叉树作左平衡旋转处理void RightBalance(BSTree &T); //对以指针T所指结点为根的二叉树作右平衡旋转处理bool InsertAVL(BSTree &T,int e,bool &taller); //插入结点e bool SearchBST(BSTree &T,int key); //查找元素key是否在树T中 void LeftBalance_div(BSTree &p,int &shorter); //删除结点时左平衡旋转处理 void RightBalance_div(BSTree &p,int &shorter); //删除结点时右平衡旋转处理 void Delete(BSTree q,BSTree &r,int &shorter); //删除结点 int DeleteA VL(BSTree &p,int x,int &shorter); //平衡二叉树的删除操作 void PrintBST(BSTree T,int m); //按树状打印输出二叉树的元素 2.主程序的流程 3.各模块之间的层次调用 算法与数据结构 课程设计报告 题目: A VLree的实现及分析 班级: 12计算机1 学号: 1200303132 姓名: 熊成毅 成绩: 2013年12月31日 一、AVLree的实现及分析 AVL 树是平衡的二元查找树。一株平衡的二元查找树就是指对其每一个节点,其左子树和右子树的高度只差不超过1. 编写程序实现AVL树的判别;并实现AVL树的ADT,包括其上的基本操作;节点的加入和删除。BSt和AVL的差别就在平衡性上,所以AVL的操作关键要考虑如何在保持二元查找树定义条件下对二元树进行平衡化。 (1)编写AVL树的判别程序,并判别一个人元查找数是否为AVL树。二元查找树用其先序遍历结果表示,如:5,2,1,3,7,8. (2)实现AVL树的ADT,包括其上的基本操作:节点的加入和删除,另外包括将一般二元查找树转变为AVL树的操作。 二、设计思想(宋体,三号加粗) 任意给定一组数据,设计一个算法,建立一棵平衡二叉树,对它进行查找、插入、删除等操作。平衡二叉树ADT结构如下: typedef struct{ Status key; }ElemType; typedef struct BSTNode{ ElemType data; Status bf; struct BSTNode *lchild,*rchild; }BSTNode,*BSTree; 给出一组数据,通过 InsertAVL(BSTree &T, ElemType e, Status &taller)插入算法,构建平衡二叉树,若在平衡的二叉排序树T中不存在和e有相同关键字的结点,则插入一个数据元素为e的新结点,并返回1,否则返回0。若因插入而使二叉排序树失去平衡,则作平衡旋转处理,布尔变量taller反映T长高与否。 在此算法中,利用到递归算法和 LeftBalance(BSTree &T)左平衡处理,RightBalance(BSTree &T)右平衡处理。进而实现构建平衡二叉树,使其左子树和右子树的高度之差不超过1. LeftBalance(BSTree &T)对以指针T所指结点为根的二叉树作左平衡旋转处理。本算法结束时,指针T指向新的根结点。 RightBalance(BSTree &T)// 对以指针T所指结点为根的二叉树作右平衡旋转处理。本算法结束时,指针T指向新的根结点。 R_Rotate(BSTree &p)对以*p为根的二叉排序树作右旋处理,处理之后p指向新的树根结点,即旋转处理之前的左子树的根结点 L_Rotate(BSTree &p)对以p↑为根的二叉排序树作左旋处理,处理之后p指向新的树 数据结构实习报告 题目:平衡二叉树的操作演示 班级:信息管理与信息系统11-1 姓名:崔佳 学号:201101050903 完成日期:2013.06.25 一、需求分析 1. 初始,平衡二叉树为空树,操作界面给出两棵平衡二叉树的显示、查找、插入、删除、销毁、合并两棵树,几种选择。其中查找、插入和删除操作均要提示用户输入关键字。每次插入或删除一个节点后都会更新平衡二叉树的显示。 2. 平衡二叉树的显示采用凹入表形式。 3.每次操作完毕后都会给出相应的操作结果,并进入下一次操作,知道用户选择退出 二、概要设计 1.平衡二叉树的抽象数据类型定义: ADT BalancedBinaryTree{ 数据对象D:D是具有相同特性的数据元素的集合。各个数据元素均含有类型相同,可唯一标志的数据元素的关键字。 数据关系R:数据元素同属一个集合。 基本操作P: InitAVL(BSTree& T) 操作结果:构造一个空的平衡二叉树T DestroyAVL(BSTree& T) 初始条件:平衡二叉树T存在 操作结果:销毁平衡二叉树T SearchAVL(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 BalancedBinaryTree 平衡二叉树构造方法 平衡二叉树 对于二叉查找树,尽管查找、插入及删除操作的平均运行时间为O(logn),但是它们的最差运行时间都是O(n),原因在于对树的形状没有限制。 平衡二叉树又称为AVL树,它或者是一棵空树,或者是有下列性质的二叉树:它的左子树和右子树都是平衡二叉树,且左右子树的深度之差的绝对值不超过1。二叉树的的平衡因子BF为:该结点的左子树的深度减去它的右子树的深度,则平衡二叉树的所有结点的平衡因子为只可能是:-1、0和1 一棵好的平衡二叉树的特征: (1)保证有n个结点的树的高度为O(logn) (2)容易维护,也就是说,在做数据项的插入或删除操作时,为平衡树所做的一些辅助操作时间开销为O(1) 一、平衡二叉树的构造 在一棵二叉查找树中插入结点后,调整其为平衡二叉树。若向平衡二叉树中插入一个新结点后破坏了平衡二叉树的平衡性。首先要找出插入新结点后失去平衡的最小子树根结点的指针。然后再调整这个子树中有关结点之间的链接关系,使之成为新的平衡子树。当失去平衡的最小子树被调整为平衡子树后,原有其他所有不平衡子树无需调整,整个二叉排序树就又成为一棵平衡二叉树 1.调整方法 (1)插入点位置必须满足二叉查找树的性质,即任意一棵子树的左结点都小于根结点,右结点大于根结点 (2)找出插入结点后不平衡的最小二叉树进行调整,如果是整个树不平衡,才进行整个树的调整。 2.调整方式 (1)LL型 LL型:插入位置为左子树的左结点,进行向右旋转 由于在A的左孩子B的左子树上插入结点F,使A的平衡因子由1变为2,成为不平衡的最小二叉树根结点。此时A结点顺时针右旋转,旋转过程中遵循“旋转优先”的规则,A结点替换D结点成为B结点的右子树,D结点成为A结点的左孩子。 (2)RR型 RR型:插入位置为右子树的右孩子,进行向左旋转 由于在A的右子树C的右子树插入了结点F,A的平衡因子由-1变为-2,成为不平衡的最小二叉树根结点。此时,A结点逆时针左旋转,遵循“旋转优先”的规则,A结点替换D结点成为C的左子树,D结点成为A的右子树。 (3)LR型 LR型:插入位置为左子树的右孩子,要进行两次旋转,先左旋转,再右旋转;第一次最小不平衡子树的根结点先不动,调整插入结点所在的子树,第二次再调整最小不平衡子树。 由于在A的左子树B的右子树上插入了结点F,A的平衡因子由1变为了2,成为不平衡的最小二叉树根结点。第一次旋转A结点不动,先将B的右子树的根结点D向左上旋转提升到B结点的位置,然后再把该D结点向右上旋转提升到A结点的位置。 (4)RL型 RL型:插入位置为右子树的左孩子,进行两次调整,先右旋转再左旋转;处理情况与LR 类似。 数据结构程序报告(平衡二叉树的操作) 计算机科学学院数据结构课程设计报告 平衡二叉树操作 学生姓名: 学号: 班级: 指导老师: 报告日期: 1.需求分析 1.建立平衡二叉树并进行创建、查找、插入、删除等功能。 2.设计一个实现平衡二叉树的程序,可进行创建、查找、插入、删除等操作,实现动态的输入数据,实时的输出该树结构。 3.测试数据:自选数据 2.概要设计 1.抽象数据类型定义: typedef struct BSTNode { int data; int bf; //节点的平衡因子 struct BSTNode *lchild,*rchild; //左右孩子指针 }BSTNode,*BSTree; void CreatBST(BSTree &T); //创建平衡二叉树 void R_Rotate(BSTree &p); //对以*p 为根的二叉排序树作左旋处理 void L_Rotate(BSTree &p); //对以*p 为根的二叉排序树作左旋处理 void LeftBalance(BSTree &T); //对以指针T所指结点为根的二叉树作左平衡旋转处理void RightBalance(BSTree &T); //对以指针T所指结点为根的二叉树作右平衡旋转处理bool InsertA VL(BSTree &T,int e,bool &taller); //插入结点e bool SearchBST(BSTree &T,int key); //查找元素key是否在树T中 void LeftBalance_div(BSTree &p,int &shorter); void RightBalance_div(BSTree &p,int &shorter); 平衡二叉树(AVL)查找、插入和删除 小组成员: 陈静101070009 陈丹璐101070006 陈娇101070008 目录 平衡二叉树(AVL) (1) 查找、插入和删除 (1) 问题描述 (2) 设计说明 (3) (一)ADT (3) (二)算法思想 (5) (三)数据结构 (12) (四)程序结构与流程 (13) 运行平台及开发工具 (15) I/O格式 (15) 算法复杂度分析 (18) 源代码 (18) 小结 (37) 问题描述 利用平衡二叉树实现一个动态查找表。 (1)实现动态查找表的三种基本功能:查找、插入和删除。 (2)初始时,平衡二叉树为空树,操作界面给出创建、查找、插入和删除和退出五种操作供选择。每种操作均要提示输入关键字。创建时,根据提示输入数据,以-1为输入数据的结束标志,若输入数据重复,则给出已存在相同关键字的提示,并不将其插入到二叉树中。在查找时,如果查找的关键字不存在,则显示不存在查找的关键字,若存在则显示存在要查找的关键字。插入时首先检验原二叉树中是否已存在相同第3 页共38 页- 3 -的关键字,若没有则进行插入并输出二叉树,若有则给出已有相同关键字的提醒。删除时首先检验原二叉树中是否存在要删除的关键字,若有则进行删除后并输出二叉树,若没有则给出不存在要删除的关键字的提醒。 (3)平衡二叉树的显示采用中序遍历的方法输出,还可以根据输出数据是否有序验证对平衡二叉树的操作是否正确。 设计说明 (一)ADT ADT BalancedBinaryTree{ 数据对象D:D是具有相同特性的数据元素的集合。各个数据元素均含有类型相同,可唯一标志的数据元素的关键字。 数据关系R:数据元素同属一个集合。 基本操作P: void R_Rotate(BSTree &p); 初始条件:二叉树存在,且关键字插入到以*p为根的二叉树的左子树的左孩子上; 操作结果:对以*p为根的二叉排序树作右旋处理 数据结构课程设计 课程名称:平衡二叉树的生成 院系:信息工程学院 年级专业:10级计科 学号: 学生姓名: 指导教师: 开题时间: 2010 年 12 月 01 日 完成时间: 2010 年 12 月 31 日 信息工程学院 X X X X X X X数据结构课程设计成绩评定表 院系:信息工程学院年级专业: 学号:姓名: 摘要 本篇论文系计科专业10年末课程设计论文,按照相应要求写作而成。 主要讨论的是平衡二叉树的生成问题,借助本程序可以由用户输入数值,并生成平衡二叉树,并可以对数据进行方便的修改和删除添加,任意插入或删除一个结点后仍然要求任然构成平衡二叉树,并按中序遍历输出这棵平衡二叉树。· 本论文共由五个章构成,每个内容独立成章,各章下设相应子章节。 各个章节逐渐递进,分别是: 第一章:需求分析 第二章系统设计 第三章编码 第四章测试 第五章维护 本论文特点: 1.论述清楚,目录详尽,可以方便的查询相应章节,方便使用。 2.图文结合,几乎没一个子程序模块都有相应的流程图与之对应,有利于读者理解每 个子程序的设计思路。 3.模块分化清晰,每个模块独立成节,又彼此联系,深化了C语言模块化编程的特点。 4.测试模块配合对应的运行截图,真实可信,对读者理解程序的运行情况起到了很大 作用。 5.程序清单完整详细,解释详细。 目录 第一章需求分析 (1) 1.1功能描述------------------------------------------------1 1.2数据词典------------------------------------------------1 第二章系统设计 (3) 2.1 基本概念介绍----------------------------------------------3 2.2 总体设计--------------------------------------------------8 2.3 插入结点-------------------------------------------------10 2.4 删除结点-------------------------------------------------11 2.5 中序遍历-------------------------------------------------11 第三章编码 (12) 3.1 总体编码------------------------------------------------12 3.2 总流程图------------------------------------------------15 3.3 以指针T所指结点为根的二叉树作右平衡旋转处理------------16 第四章测试 (17) 4.1 创建二叉树测试-------------------------------------------17 4.2 插入结点测试---------------------------------------------19 4.3 删除结点测试---------------------------------------------20 4.4中序遍历结点测试------------------------------------------21 4.5 先序遍历测试---------------------------------------------21 第五章维护 (22) 5.1维护----------------------------------------------------22 https://www.wendangku.net/doc/d67952868.html, Python数据结构——AVL树的实现_光环大数据Python培训 我们已经证明,保持 AVL 树的平衡将会使性能得到很大的提升,那我们看看如何在程序中向树插入一个新的键值。因为所有的新键是作为叶节点插入树的,而新叶子的平衡因子为零,所以我们对新插入的节点不作调整。不过一旦有新叶子的插入我们必须更新其父节点的平衡因子。新叶子会如何影响父节点的平衡因子取决于叶节点是左子节点还是右子节点。如果新节点是右子节点,父节点的平衡因子减 1。如果新节点是左子节点,父节点的平衡因子将加 1。这种关系可以递归地应用于新节点的前两个节点,并有可能影响到之前的每一个甚至是根节点。由于这是一个递归的过程,我们看看更新平衡因子的两个基本条件: 递归调用已到达树的根。 父节点的平衡因子已调整为零。一旦子树平衡因子为零,那么父节点的平衡因子不会发生改变。 我们将实现 AVL 树的子类BinarySearchTree。首先,我们将重写_put方法,并写一个新的辅助方法updateBalance。这些方法如Listing 1 所示。除了第 7 行和第 13 行对 updateBalance的调用,你会注意到_put和简单的二叉搜索树的定义完全相同。 Listing 1 updateBalance方法完成了大部分功能,实现了我们刚提到的递归过程。这个再平衡方法首先检查当前节点是否完全不平衡,以至于需要重新平衡(第 16 行)。如果当前节点需要再平衡,那么只需要对当前节点进行再平衡,而不需要 https://www.wendangku.net/doc/d67952868.html, 进一步更新父节点。如果当前节点不需要再平衡,那么父节点的平衡因子就需要调整。如果父节点的平衡因子不为零,算法通过父节点递归调用updateBalance 方法继续递归到树的根。 当对一棵树进行再平衡是必要的,我们该怎么做呢?高效的再平衡是使 AVL 树能够很好地执行而不牺牲性能的关键。为了让 AVL 树恢复平衡,我们会在树上执行一个或多个“旋转”(rotation)。 为了了解什么是旋转,让我们看一个很简单的例子。思考一下图 3 的左边的树。这棵树是不平衡的,平衡因子为 -2。为了让这棵树平衡我们将根的子树节点 A 进行左旋转。 图 3:使用左旋转变换不平衡树 执行左旋转我们需要做到以下几点: 使右节点(B)成为子树的根。 移动旧的根节点(A)到新根的左节点。 如果新根(B)原来有左节点,那么让原来B的左节点成为新根左节点(A)的右节点。 注:由于新根(B)是 A 的右节点,在这种情况下,移动后的 A 的右节点一定是空的。我们不用多想就可以给移动后的 A 直接添加右节点。 虽然这个过程概念上看起来简单,但实现时的细节有点棘手,因为要保持二叉搜索树的所有性质,必须以绝对正确的顺序把节点移来移去。此外,我们需要确保更新了所有的父节点。让我们看一个稍微复杂的树来说明右旋转。图 4 的左侧展现了一棵“左重”的树,根的平衡因子为 2。执行一个正确的右旋转,我 实现平衡二叉排序树的各种算法代码一 /* 《实现平衡二叉排序树的各种算法》 一、分析题目要求 用函数实现如下平衡二叉排序树算法,: (1)插入新结点 (2)前序、中序、后序遍历二叉树(递归) (3)前序、中序、后序遍历的非递归算法 (4)层次遍历二叉树 (5)在二叉树中查找给定关键字(函数返回值为成功1,失败0) (6)交换各结点的左右子树 (7)求二叉树的深度 (8)叶子结点数 (9)删除某结点 为了完成以上的各项操作,首先应该用函数建一棵平衡二叉排序树,输入形式是首先输入要建的二叉树的结点数,然后依次输入各个结点的值。在实现插入新结点的函数时,需要一个向一棵二叉树插入新结点的函数。可用递归算法写出平衡二叉树的前序,中序,后序遍历的函数。在写平衡二叉树的前,中,后序遍历的非递归算法时要用到栈结构的知识,运用栈结构来存储平衡二叉树结点的指针。在层次遍历二叉树时需要用到队列结构,运用队列结构的先进先出来存储二叉树的结点指针。在遍历二叉树的结点时需要一个访问结点数据的函数。二叉树是一棵排序树,所以二叉树的查找可以运用其有序的性质,查找的方式和建树的方式相似。交换二叉树各结点的左右子树时,可以用先序遍历递归的方式从根结点向下递归,每次访问结点时就需将各结点的左右孩子的指针调换,并对该结点的平衡因子作相应的处理。示二叉树的深度时,可用递归的方式访问结点的左右子树,并记录下左右子树的深度,最后返回左右子树中较深的深度的值即可。可以用一次遍历的方式遍历二叉树,记录每一个经过的结点,若结点存在且左右孩子都为空,则该结点为叶子结点。删除二叉树的某个结点时,首先要写一个函数,用递归查找的方式找到相应的结点,该函数还要有调整二叉树平衡的作用,因为若删除结点使得二叉树深度减少而不平衡,需要调整二叉树的平衡,若该结点不存在则返回ERROR,,若存在该结点,则应该再写一个函数来删除该结点,在删除之前还要判断该结点是只有左子树还是只有右子树还是左右子树都有的情况:若只有左或是只有右子树,则只需删除该结点,并回溯调整二叉树的平衡;若该结点的左右子树都有,则应该用另一个函数递归找到该结点的直接“后继”,并从该“后继”开始回溯调整二叉树的平衡。 */ #include<stdio.h> #include<stdlib.h> #include<malloc.h> #define OK 1 #define ERROR 0 哈尔滨工业大学计算机科学与技术学院 实验报告 课程名称:数据结构与算法 课程类型:必修 实验项目名称:查找结构与排序算法实验题目:建立A VL树 目录 目录 (2) 一、实验目的 (3) 二、实验要求及实验环境 (3) 1.实验要求: (3) 2.实验环境: (3) 三、设计思想 (3) 1.逻辑设计 (3) (1)平衡查找二叉树 (3) (2)平衡因子 (4) (3)失衡情况与修正操作 (4) 2.物理设计 (5) (1)存储结构 (5) (2)建立平衡二叉查找树 (6) (3)插入新结点 (6) (4)删除结点 (11) 四、测试结果 (15) 五、系统不足与经验体会 (15) 六、附录:源代码(带注释) (16) 一、实验目的 通过实现A VL树的建立、插入与删除,掌握A VL树结构。 二、实验要求及实验环境 1.实验要求: 要求: 1.具有插入(建立)、删除和查找功能 2.插入操作应包括四种类型的平衡化处理 3.删除操作应包括四种类型的平衡化处理并且包括多次平衡化处理 4.能体现操作前后二叉树的形态及其变化 2.实验环境: Microsoft Windows7, Code::Blocks 10.05 三、设计思想 1.逻辑设计 (1)平衡查找二叉树 平衡二叉树的定义是: 平衡二叉树或为空树,或满足下列特征: A若其左子树非空,则左子树上所有结点的关键字值都小于根节点关键字值B若其右子树非空,则右子树上所有结点的关键字值都大于根节点关键字值C根节点的左右子树高度之差的绝对值不超过1 D根节点的左子树和右子树仍为A VL树 平衡查找二叉树不会退化为线性链表,因此时间复杂度比较稳定。 二叉树: 左子树都小于根节点,右子树都大于根节点。可以动态维护这棵树(因为是树结构,可以有限步完成插入),所以是动态查找算法。时间复杂度为O(logn)在46.5%的情况下,需要把二叉树平衡化成“平衡二叉树”。 平衡二叉树:定义:平衡二叉树或为空树,或为如下性质的二叉排序树: (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的右子树。 攀枝花学院本科学生课程设计任务书题目二叉排序树与平衡二叉树的实现 1、课程设计的目的 1)使学生进一步理解和掌握课堂上所学各种基本抽象数据类型的逻辑结构、存储结构和操 作实现算法,以及它们在程序中的使用方法。 2)使学生掌握软件设计的基本内容和设计方法,并培养学生进行规范化软件设计的能力。 3)使学生掌握使用各种计算机资料和有关参考资料,提高学生进行程序设计的基本能力。 2、课程设计的内容和要求(包括原始数据、技术要求、工作要求等) 1) (1)以回车('\n')为输入结束标志,输入数列L,生成一棵二叉排序树T; (2)对二叉排序树T作中序遍历,输出结果; (3)计算二叉排序树T查找成功的平均查找长度,输出结果; (4)输入元素x,查找二叉排序树T,若存在含x的结点,则删该结点,并作中序遍历(执行 操作2);否则输出信息“无x”; (5)用数列L,生成平衡的二叉排序树BT:当插入新元素之后,发现当前的二叉排序树BT 不是平衡的二叉排序树,则立即将它转换成新的平衡的二叉排序树BT; (6)计算平衡的二叉排序树BT的平均查找长度,输出结果。 3、主要参考文献 [1]刘大有等,《数据结构》(C语言版),高等教育出版社 [2]严蔚敏等,《数据结构》(C语言版),清华大学出版社 [3]William Ford,William Topp,《Data Structure with C++》清华大学出版社 [4]苏仕华等,数据结构课程设计,机械工业出版社 4、课程设计工作进度计划 第1天完成方案设计与程序框图 第2、3天编写程序代码 第4天程序调试分析和结果 第5天课程设计报告和总结 指导教师(签字)日期年月日 教研室意见: 年月日学生(签字): 接受任务时间:年月日注:任务书由指导教师填写。 Java中A VL平衡二叉树实现Map (仿照TreeMap和TreeSet) 1、下面是AVLTreeMap的实现 package com; import java.io.IOException; import java.util.*; public class AVLTreeMap 数据结构课程设计:平衡二叉树 目录 1 课程设计的目的和内容.............................................. 1 课程设计目的 ................................................ 1 1.1 1.2 主要内容 (1) 2 课程设计分析 (2) 2.1 程序的目的和要求 (2) 2.2 程序的主要数据和功能模块 (2) 3 详细设计 (5) 3.1 程序主要功能模块的伪代码算法 (5) 3.2 程序主要流程图 (8) 4 测试数据与测试结果................................................ 9 5 程序的使用和改进. (14) 5.1 用户使用说明 (14) 5.2 程序的改进 (14) 6 课程设计小结..................................................... 15 7 参考文献 (15) 1 平衡二叉树 1 课程设计的目的和内容 1.1 课程设计目的 复习二叉树的三叉链表存储结构和遍历方法。 掌握二叉排序树的特点和生成方法。 掌握平衡二叉树四种不平衡形态的判定和旋转为平衡的方法。 1.2 主要内容 (1)输入结点数据,构造二叉树的结点,按二叉排序树的规则插入该结点到三叉链表中; (2)通过插入函数InsertAVL(BSTNode* &T,int key)插入新结点到二叉树中,并递归调用插入函数本身,直到正确插入到二叉树中,并返回上次递归,每返回上次递归一次同时判断其平衡度bf,找到最小不平衡树的根结点p。 (3)判断最小不平衡树的平衡因子(bf)的值,若bf>1, 则调用左平衡函数LeftBalance(),若bf<-1,则调用右平衡函RightBalance(),再判断根结点p的左(右)孩子的平衡因子(共有LL型、LR型、RR型、RL型四种),然后判定得到的不平衡形态调用不同的旋转函数即可将其重新调整为平衡二叉树; (4)重复步骤(1)(2)(3),直到所有结点都插入到该平衡二叉树中为止; (5)输出该二叉树的前序(或者后序)序列和中序序列,手工恢复出该二叉树,检验其是否为平衡二叉树;并验证其中序序列的有序性。 2 平衡二叉树 2 课程设计分析 2.1 程序的目的和要求 (1)本程序演示平衡二叉树的插入,以及AVL的前序遍历和中序遍历,并且验证其中序遍历有序性。 (2)对平衡二叉树出现的的的LL,LR,RL,RR四种情况进行处理是其平衡。 (3)接着要实现平衡二叉树的插入,其中根据平衡二叉树插入的算法要不停的把插入的元素平衡地插入,需要判断平衡并调用左右旋转函数,更新平衡二叉树 2.2 程序的主要数据和功能模块 (1)程序主要数据 平衡二叉树左右子树的深度:ldep,rdep A VL树的插入 再向一颗本来是高度平衡的A VL树中插入一个新节点是,如果树中的某个节点的平衡因子的绝对值|bf|>1,则出现了不平衡,需要做平衡化处理。 设新插入的节点为p,从节点p到根节点的路径上,每个节点为根的子树的高度都可能增加1,因此在每执行一次二叉搜索树的插入运算后,都需要从新插入的节点p开始,沿该节点的插入路径向根节点方向回溯,修改各节点的平衡因子,调整子树的高度,恢复被破换的平衡性质。 新节点p的平衡因子为0。现在考察它的父节点pr,若p是pr的右子女,则pr的平衡因子增加1,否则pr的平衡因子减少1,按照修改后pr的平衡因子值有三种情况: 1、节点pr的平衡因子为0,说明刚才是在pr的较矮的子树上插入了新节点,节点 pr处平衡,且高度没有增减,此时从pr到根的路径上各节点为根的子树高度 不变,从而各各节点的平衡因子不变,可以结束重新平衡化的处理,返回主程 序。 2、节点pr的平衡因子绝对值bf=1,说明插入前pr的平衡因子是0,插入新节点后, 以pr为根的子树没有失去平衡,不需要平衡化旋转,但该子树的高度增加,还 需从节点pr向根的方向回溯,继续考察节点pr的父节点的平衡状态。 3、节点pr的平衡因子的绝对值bf=2,说明新节点在较高的子树上插入,造成了 不平很,需要做平衡化旋转,分两种情况考虑: 3.1 若节点pr的bf=2,说明右子树高,结合其右子女q的bf分别处理: 1\若q的bf=1,执行左单旋转; 2\若q的bf=-1, 执行先右后左双旋转 3.2 若节点pr的bf=-2,说明左子树高,结合其左子女q的bf分别处理: 1\若q的bf=-1,执行右单旋转; 2\若q的bf= 1, 执行先左后右双旋转 A VL树的删除 若删除节点后破坏了A VL树的平衡,则需要进行平衡旋转 1、如果被删除节点p有两个子女节点,首先搜索p在中序下的直接前驱q(也可 以是直接后继),再把节点q的内容传送给节点p,问题转移到删除节点q,把节 点q当做被删除节点p,它是只有一个子女的节点。 2、如果被删除节点p最多只有一个子女q,可以简单的把p的父节点pr中原来指 向的指针该指到q,如果节点p没有子女,p父节点pr的相应指针为NULL,然 后将原来的节点pr为根的子树的高度减1,并沿pr通向根的路径反向追踪高度 的这一变化对路径上各节点的影响; 考察节点q的父节点pr,若q是pr的左子女,则pr的平衡因子增加1,否则减少1,根据修改后的pr的平衡因子,按三种情况分别进行处理: (1)pr的平衡因子原来为0,在它的左子树或右子树被缩短后,则它的平衡因子改为 1或-1,由于以pr为根的子树高度没有改变,从pr到根节点的路径上所有节点 都不需要调整,此时可结束本次删除的重新平衡过程。 (2)节点pr的平衡因子原不为0,且较高的子树被缩短,则p的平衡因子改为0, 此时pr为根的子树平衡,但其高度减1,为此需要继续考察节点pr的父节点的 平衡状态, (3)节点pr的平衡因子原不为0,且较矮的子树被缩短,则在节点pr发生不平衡, 课程设计报告 课程名称数据结构课程设计 题目平衡二叉树操作 指导教师 设计起止日 2010-5-16 学院计算机学院 专业软件工程 学生姓名 班级/学号------------ 成绩_________________ 一.需求分析 1、建立平衡二叉树并进行创建、增加、删除、调平等操作。 2、设计一个实现平衡二叉树的程序,可进行创建、增加、删除、调平等操作,实现动态的输入数据,实时的输出该树结构。 3、测试数据:自选数据 二.概要设计 平衡二叉树是在构造二叉排序树的过程中,每当插入一个新结点时,首先检查是否因插入新结点而破坏了二叉排序树的平衡性,若是,则找出其中的最小不平衡子树,在保持二叉排序树特性的前提下,调整最小不平衡子树中各结点之间的链接关系,进行相应的旋转,使之成为新的平衡子树。具体步骤如下: ⑴每当插入一个新结点,从该结点开始向上计算各结点的平衡因子,即计算该结点的祖先结点的平衡因子,若该结点的祖先结点的平衡因子的绝对值均不超过1,则平衡二叉树没有失去平衡,继续插入结点; ⑵若插入结点的某祖先结点的平衡因子的绝对值大于1,则找出其中最小不平衡子树的根结点; ⑶判断新插入的结点与最小不平衡子树的根结点的关系,确定是哪种类型的调整; ⑷如果是LL型或RR型,只需应用扁担原理旋转一次,在旋转过程中,如果出现冲突,应用旋转优先原则调整冲突;如果是LR型或RL型,则需应用扁担原理旋转两次,第一次最小不平衡子树的根结点先不动,调整插入结点所在子树,第二次再调整最小不平衡子树,在旋转过程中,如果出现冲突,应用旋转优先原则调整冲突; ⑸计算调整后的平衡二叉树中各结点的平衡因子,检验是否因为旋转而破坏其他结点的平衡因子,以及调整后的平衡二叉树中是否存在平衡因子大于1的结点。 三.详细设计 树的内部变量 typedef struct BTNode { AVL树插入删除 AVL树是一种平衡二叉树,其每个节点的左右子树高度最多差1,空树高度定为-1,当左右的高度超过1,即失去了平衡,不是AVL树了。 private static class AVLNode数据结构平衡二叉树的操作演示
平衡二叉树的生成过程
数据结构程序报告(平衡二叉树的操作)
数据结构课程设计AVL树实现及其分析实验报告
平衡二叉树操作演示
平衡二叉树 构造方法(绝妙)
数据结构程序报告(平衡二叉树的操作)
平衡二叉树(AVL)的查找、插入和删除
平衡二叉树-数据结构课程设计论文【可运行测试】
Python数据结构——AVL树的实现_光环大数据Python培训
实现平衡二叉排序树的各种算法代码 一
数据结构-实验4-建立AVL树
平衡二叉树
二叉排序树与平衡二叉树的实现课程设计
Java中AVL平衡二叉树实现Map (仿照TreeMap和TreeSet)
数据结构课程设计:平衡二叉树
AVL树的插入和删除
数据结构课程设计-_平衡二叉树操作
AVL树插入删除