数据结构课程设计:平衡二叉树
数据结构c语言课设-二叉树排序

题目:二叉排序树的实现1 内容和要求1)编程实现二叉排序树,包括生成、插入,删除;2)对二叉排序树进展先根、中根、和后根非递归遍历;3)每次对树的修改操作和遍历操作的显示结果都需要在屏幕上用树的形状表示出来。
4)分别用二叉排序树和数组去存储一个班(50 人以上)的成员信息(至少包括学号、姓名、成绩3 项),比照查找效率,并说明在什么情况下二叉排序树效率高,为什么?2 解决方案和关键代码2.1 解决方案:先实现二叉排序树的生成、插入、删除,编写DisplayBST函数把遍历结果用树的形状表示出来。
前中后根遍历需要用到栈的数据构造,分模块编写栈与遍历代码。
要求比照二叉排序树和数组的查找效率,首先建立一个数组存储一个班的成员信息,分别用二叉树和数组查找,利用clock〔〕函数记录查找时间来比照查找效率。
2.2关键代码树的根本构造定义及根本函数typedef struct{KeyType key;} ElemType;typedef struct BiTNode//定义链表{ElemType data;struct BiTNode *lchild, *rchild;}BiTNode, *BiTree, *SElemType;//销毁树int DestroyBiTree(BiTree &T){if (T != NULL)free(T);return 0;}//清空树int ClearBiTree(BiTree &T){if (T != NULL){T->lchild = NULL;T->rchild = NULL;T = NULL;}return 0;}//查找关键字,指针p返回int SearchBST(BiTree T, KeyType key, BiTree f, BiTree &p) {if (!T){p = f;return FALSE;}else if EQ(key, T->data.key){p = T;return TRUE;}else if LT(key, T->data.key)return SearchBST(T->lchild, key, T, p);elsereturn SearchBST(T->rchild, key, T, p);}二叉树的生成、插入,删除生成void CreateBST(BiTree &BT, BiTree p){int i;ElemType k;printf("请输入元素值以创立排序二叉树:\n");scanf_s("%d", &k.key);for (i = 0; k.key != NULL; i++){//判断是否重复if (!SearchBST(BT, k.key, NULL, p)){InsertBST(BT, k);scanf_s("%d", &k.key);}else{printf("输入数据重复!\n");return;}}}插入int InsertBST(BiTree &T, ElemType e){BiTree s, p;if (!SearchBST(T, e.key, NULL, p)){s = (BiTree)malloc(sizeof(BiTNode));s->data = e;s->lchild = s->rchild = NULL;if (!p)T = s;else if LT(e.key, p->data.key)p->lchild = s;elsep->rchild = s;return TRUE;}else return FALSE;}删除//某个节点元素的删除int DeleteEle(BiTree &p){BiTree q, s;if (!p->rchild) //右子树为空{q = p;p = p->lchild;free(q);}else if (!p->lchild) //左子树为空{q = p;p = p->rchild;free(q);}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;elseq->lchild = s->lchild;delete s;}return TRUE;}//整棵树的删除int DeleteBST(BiTree &T, KeyType key) //实现二叉排序树的删除操作{if (!T){return FALSE;}else{if (EQ(key, T->data.key)) //是否相等return DeleteEle(T);else if (LT(key, T->data.key)) //是否小于return DeleteBST(T->lchild, key);elsereturn DeleteBST(T->rchild, key);}return 0;}二叉树的前中后根遍历栈的定义typedef struct{SElemType *base;SElemType *top;int stacksize;}SqStack;int InitStack(SqStack &S) //构造空栈{S.base = (SElemType*)malloc(STACK_INIT_SIZE *sizeof(SElemType));if (!S.base) exit(OVERFLOW);S.top = S.base;S.stacksize = STACK_INIT_SIZE;return OK;}//InitStackint Push(SqStack &S, SElemType e) //插入元素e为新栈顶{if (S.top - S.base >= S.stacksize){S.base = (SElemType*)realloc(S.base, (S.stacksize + STACKINCREMENT)*sizeof(SElemType));if (!S.base) exit(OVERFLOW);S.top = S.base + S.stacksize;S.stacksize += STACKINCREMENT;}*S.top++ = e;return OK;}//Pushint Pop(SqStack &S, SElemType &e) //删除栈顶,应用e返回其值{if (S.top == S.base) return ERROR;e = *--S.top;return OK;}//Popint StackEmpty(SqStack S) //判断是否为空栈{if (S.base == S.top) return TRUE;return FALSE;}先根遍历int PreOrderTraverse(BiTree T, int(*Visit)(ElemType e)) {SqStack S;BiTree p;InitStack(S);p = T;while (p || !StackEmpty(S)){if (p){Push(S, p);if (!Visit(p->data)) return ERROR;p = p->lchild;}else{Pop(S, p);p = p->rchild;}}return OK;}中根遍历int InOrderTraverse(BiTree T, int(*Visit)(ElemType e)) {SqStack S;BiTree p;InitStack(S);p = T;while (p || !StackEmpty(S)){if (p){Push(S, p);p = p->lchild;}else{Pop(S, p);if (!Visit(p->data)) return ERROR;p = p->rchild;}}return OK;}后根遍历int PostOrderTraverse(BiTree T, int(*Visit)(ElemType e)) {SqStack S, SS;BiTree p;InitStack(S);InitStack(SS);p = T;while (p || !StackEmpty(S)){if (p){Push(S, p);Push(SS, p);p = p->rchild;}else{if (!StackEmpty(S)){Pop(S, p);p = p->lchild;}}}while (!StackEmpty(SS)){Pop(SS, p);if (!Visit(p->data)) return ERROR;}return OK;}利用数组存储一个班学生信息ElemType a[] = { 51, "陈继真", 88,82, "黄景元", 89,53, "贾成", 88,44, "呼颜", 90,25, "鲁修德", 88,56, "须成", 88,47, "孙祥", 87, 38, "柏有患", 89, 9, " 革高", 89, 10, "考鬲", 87, 31, "李燧", 86, 12, "夏祥", 89, 53, "余惠", 84, 4, "鲁芝", 90, 75, "黄丙庆", 88, 16, "李应", 89, 87, "杨志", 86, 18, "李逵", 89, 9, "阮小五", 85, 20, "史进", 88, 21, "秦明", 88, 82, "杨雄", 89, 23, "刘唐", 85, 64, "武松", 88, 25, "李俊", 88, 86, "卢俊义", 88, 27, "华荣", 87, 28, "杨胜", 88, 29, "林冲", 89, 70, "李跃", 85, 31, "蓝虎", 90, 32, "宋禄", 84, 73, "鲁智深", 89, 34, "关斌", 90, 55, "龚成", 87, 36, "黄乌", 87, 57, "孔道灵", 87, 38, "张焕", 84, 59, "李信", 88, 30, "徐山", 83, 41, "秦祥", 85, 42, "葛公", 85, 23, "武衍公", 87, 94, "范斌", 83, 45, "黄乌", 60, 67, "叶景昌", 99, 7, "焦龙", 89, 78, "星姚烨", 85, 49, "孙吉", 90, 60, "陈梦庚", 95,};数组查询函数void ArraySearch(ElemType a[], int key, int length){int i;for (i = 0; i <= length; i++){if (key == a[i].key){cout << "学号:" << a[i].key << " 姓名:" << a[i].name << " 成绩:" << a[i].grade << endl;break;}}}二叉树查询函数上文二叉树根本函数中的SearchBST()即为二叉树查询函数。
平衡二叉树

编辑
红黑树
红黑树是一种自平衡二叉查找树,是在计算机科学中用到的一种数据结构,典型的用途是实现关联数组。它是在1972年由Rudolf Bayer发明的,他称之为"对称二叉B树",它现代的名字是在 Leo J. Guibas 和 Robert Sedgewick 于1978年写的一篇论文中获得的。它是复杂的,但它的操作有着良好的最坏情况运行时间,并且在实践中是高效的: 它可以在O(log n)时间内做查找,插入和删除,这里的n是树中元素的数目。
伸展树
伸展树(Splay Tree)是一种二叉排序树,它能在O(log n)内完成插入、查找和删除操作。它由Daniel Sleator和Robert Tarjan创造。它的优势在于不需要记录用于平衡树的冗余信息。在伸展树上的一般操作都基于伸展操作。
SBT
Size Balanced Tree(简称SBT)是一自平衡二叉查找树,是在计算机科学中用到的一种数据结构。它是由中国广东中山纪念中学的陈启峰发明的。陈启峰于2006年底完成论文《Size Balanced Tree》,并在2007年的全国青少年信息学奥林匹克竞赛冬令营中发表。由于SBT的拼写很容易找到中文谐音,它常被中国的信息学竞赛选手和ACM/ICPC选手们戏称为“傻B树”、“Super BT”等。相比红黑树、AVL树等自平衡二叉查找树,SBT更易于实现。据陈启峰在论文中称,SBT是“目前为止速度最快的高级二叉搜索树”。SBT能在O(log n)的时间内完成所有二叉搜索树(BST)的相关操作,而与普通二叉搜索树相比,SBT仅仅加入了简洁的核心操作Maintain。由于SBT赖以保持平衡的是size域而不是其他“无用”的域,它可以很方便地实现动态顺序统计中的select和rank操作。
平衡二叉树

#define RH -1 //右高
//平衡二叉树的类型
struct AVLNode
{
int data;
int bf; //bf结点的平衡因子,只能够取0,-1,1,为左子树的深度减去右子树的深度
struct AVLNode *lchild,*rchild; //左、右孩子指针
{
AVLNode *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;
};
2.右旋操作:
void R_Rotate(AVLNode *&p)//LL型算法
{
AVLNode *lc=p->lchild; // lc指向p的左子树根结点
p->lchild=lc->rchild; // lc的右子树挂接为p(之前跟节点)的左子树
lc->rchild=p;
p=lc; // p指向新的根结点
插入和删除:
插入删除是互为镜像的操作。我们可以采用前面对二叉排序树的删除操作来进行。然后,在删除掉结点后,再对平衡树进行平衡化处理。删除之所以删除操作需要的平衡化可能比插入时次数多,就是因为平衡化不会增加子树的高度,但是可能会减少子树的高度,在有有可能使树增高的插入操作中,一次平衡化能抵消掉增高;在有可能使树减低的删除操作中,平衡化可能会带来祖先节点的不平衡。AVL树体现了一种平衡的美感,两种旋转是互为镜像的,插入删除是互为镜像的操作,没理由会有那么大的差别。实际上,平衡化可以统一的这样来操作:
数据结构:第9章 查找2-二叉树和平衡二叉树

return(NULL); else
{if(t->data==x) return(t);
if(x<(t->data) return(search(t->lchild,x));
else return(search(t->lchild,x)); } }
——这种既查找又插入的过程称为动态查找。 二叉排序树既有类似于折半查找的特性,又采用了链表存储, 它是动态查找表的一种适宜表示。
注:若数据元素的输入顺序不同,则得到的二叉排序树形态 也不同!
讨论1:二叉排序树的插入和查找操作 例:输入待查找的关键字序列=(45,24,53,45,12,24,90)
二叉排序树的建立 对于已给定一待排序的数据序列,通常采用逐步插入结点的方 法来构造二叉排序树,即只要反复调用二叉排序树的插入算法 即可,算法描述为: BiTree *Creat (int n) //建立含有n个结点的二叉排序树 { BiTree *BST= NULL;
for ( int i=1; i<=n; i++) { scanf(“%d”,&x); //输入关键字序列
– 法2:令*s代替*p
将S的左子树成为S的双亲Q的右子树,用S取代p 。 若C无右子树,用C取代p。
例:请从下面的二叉排序树中删除结点P。
F P
法1:
F
P
C
PR
C
PR
CL Q
CL QL
Q SL
S PR
QL S
SL
法2:
F
PS
C
PR
CL Q
QL SL S SL
数据结构:二叉树、平衡二叉树、红黑树详解

数据结构:⼆叉树、平衡⼆叉树、红⿊树详解⼀、⼆叉树(binary tree)指每个节点最多含有两个⼦树的树结构。
时间复杂度为O(log N),在退化成链表的情况下时间复杂度为O(N)。
特点:1.所有节点最多拥有两个⼦节点;2.节点的左⼦树只包含⼩于当前根节点的数,节点的右⼦树只包含⼤于当前根节点的数。
缺点:只会以我们第⼀次添加的节点为根节点,如果后⾯添加的节点值都⼤于或⼩于根节点的值,在这种情况下会退化成链表。
⼆、平衡⼆叉树(Balanced Binary Tree)⼜称为AVL树,具有⼆叉树的全部特性,解决⼆叉树退化成链表情况的问题,每个节点的左⼦树和右⼦树的⾼度之差不会超过1,AVL树是严格的平衡⼆叉树,追求完全平衡,⽐较严格。
缺点:由于要求每个节点的左⼦树和右⼦树⾼度之差不超过1,这个要求⾮常严格,追求完全平衡,这就导致了在频繁插⼊和删除的场景中,可能就会导致AVL树失去平衡,AVL树就需要频繁的通过左旋右旋使其重新达到平衡,这时就会时得其性能⼤打折扣。
三、红⿊树和AVL树相⽐,红⿊树放弃追求完全平衡,⽽是追求⼤致平衡,保证每次插⼊节点最多只需要三次旋转就能达到平衡,维持平衡的耗时较少,实现起来也更为简单,它的旋转次数较少,对于频繁插⼊和删除操作的场景,相⽐AVL树,红⿊树更具优势。
特征:1.红⿊树是也是平衡⼆叉树实现的⼀种⽅式2.节点只能是⿊⾊或者红⾊,root根节点⼀定是⿊⾊3.新增时默认新增的节点是红⾊,不允许两个红⾊节点相连4.红⾊节点的两个⼦节点⼀定是⿊⾊红⿊树变换规则三种规则:1.改变节点颜⾊2.左旋转3.右旋转变⾊的情况:当前节点的⽗亲节点是红⾊,并且它的祖⽗节点的另外⼀个⼦节点(叔叔节点)也是红⾊:以当前节点为指针进⾏操作1.将⽗亲节点变为⿊⾊2.将叔叔节点变为⿊⾊3.将祖⽗节点变为红⾊4.再把指针定义到祖⽗节点进⾏旋转操作左旋转:当⽗亲节点为红⾊情况,叔叔节点为⿊⾊情况,且当前节点是右⼦树,左旋转以⽗节点作为左旋。
数据结构课程设计

数据结构课程设计实验1 线性表及其应用1.集合的并、交和差【问题描述】编制一个能演示执行集合的并、交和差运算的程序【基本要求】1)集合的元素限定为小写字母;2)演示程序以用户和计算机的对话方式执行。
void Union(OrderedSet &T,OrderedSet S1, OrderedSet S2){//求已建成的集合Sl和S2的并集T,即:S1.head!=NULL且S2.head!=NULL if(InitList(T){pl=GetEiemPos(Sl,1);p2=GetElemPos(S2,l);while(pl&&p2){cl=Elem(pl); c2=Elem(p2);if(cl<=c2){Append(T,Copy(pl);pl=SuccNode(pl);if(cl==c2) p2=SuccNode(p2);}else{ Append(T,Copy(p2)); p2=SuccNode(p2); }while(pl){ Append( T,Copy(pl)); pl=SuccNode(pl);}while(p2){Append(T,Copy(p2)); p2=SuccNode(p2);}}}//Unionvotd Intersection(OrderedSet &T,OrderedSet S1; OrderedSet S2) {//求集合 Sl 和 S2 的交集 Tif(!InitList(T)) T.head =NULL;else{pl=GetElemPos(S1,1);p2=GetElemPos(S2,l);while(pl&&p2){c1=Elem(p1);c2=Elem(p2);if(cl<c2) pl=SuccNode(pl);else if(cl>c2) p2=SuccNode(p2);else{ //cl==c2Append(T,Copy(pl));pl=SuccNode(pl);p2=SuccNode(p2);}//else}//while}// else}//Intersectionvoid Difference(OrderedSet &T,OrderedSet S1,OrderedSet S2) {//求集合Sl和S2的差集Tif(!InitList(T)) T.head =NULL;else {pl =GetElemPos(S1,l);p2=GetElemPos(S2,1);while(pl&&p2){cl=Elem(pl);c2=Elem(p2);if(cl<c2){Append(T,Copy(pl));pl=SuccNode(pl)else if(cl>c2) p2=SuccNode(p2);else // Cl ==c2{pl =SuccNode(p1);p2=SuccNode(p2);}}//whilewhile(pl){Apend(T,Copy(pl));p =SuccNode(pl);}}//else}//Differencevoid WriteSetElem(LinkType p){//显示集合的一个元素pramtk'Jh WriteElem(Elem(p));}//WriteSetElemvotd Printset(OrderedSet T){//显示集合的全部元素p=GetElemPos(T,1);printf('[']);if(p){WriteElem(Elem(p);p=SuccNode(p);}ListTraverse(p,WriteSetElem());Prtntf(')]');}//Printset实验2 栈、队列和递归程序设计2. 迷宫问题。
名词解释平衡二叉树

平衡二叉树介绍平衡二叉树(Balanced Binary Tree),简称AVL树,是一种特殊的二叉搜索树。
在平衡二叉树中,任意节点的左子树和右子树的高度之差不超过1。
这种平衡性的特点使得平衡二叉树的查找、插入和删除操作的时间复杂度保持在O(log n)级别,极大地提高了数据结构的效率。
定义和性质平衡二叉树是一种特殊的二叉搜索树,满足以下性质: 1. 空树或者任意节点的左右子树高度之差的绝对值不超过1。
2. 左子树和右子树都是平衡二叉树。
对于平衡二叉树,我们还可以得出一些重要的结论: 1. 平衡二叉树的任意节点的左子树和右子树的高度差不超过1。
也就是说,平衡二叉树的高度是一个较小的常数倍数。
2. 平衡二叉树的最小高度是log n,最大高度是2log n。
实现方法为了保持二叉树的平衡,我们需要对插入和删除操作进行适当的调整。
下面介绍两种常见的平衡二叉树实现方法。
AVL树AVL树是最早提出的平衡二叉树之一。
在AVL树中,每个节点都会存储一个额外的信息,即平衡因子(balance factor)。
平衡因子的定义是左子树的高度减去右子树的高度。
如果平衡因子的绝对值大于1,就需要进行平衡调整。
AVL树的平衡调整分为四种情况:左-左旋转(LL),右-右旋转(RR),左-右旋转(LR),和右-左旋转(RL)。
通过这四种旋转操作,可以使得树重新达到平衡状态。
红黑树红黑树是另一种常见的平衡二叉树。
红黑树的平衡调整是通过变换节点的颜色和旋转节点来完成的。
红黑树的规则如下: 1. 每个节点要么是红色,要么是黑色。
2. 根节点是黑色。
3. 所有叶子节点(NIL节点)都是黑色。
4. 如果一个节点是红色的,则它的两个子节点都是黑色的。
5. 任意节点到其每个叶子节点的路径上包含相同数目的黑色节点。
通过对节点进行颜色变换和旋转操作,红黑树可以在插入和删除节点的过程中保持平衡。
平衡二叉树的应用平衡二叉树在计算机科学中有广泛的应用。
二叉排序树课程设计

二叉排序树课程设计一、课程目标知识目标:1. 学生能够理解二叉排序树的基本概念和性质,掌握其结构特点和应用场景。
2. 学生能够掌握二叉排序树的插入、删除和查找操作,并了解其时间复杂度。
3. 学生能够理解二叉排序树与其他排序算法的关系,了解其在排序中的应用。
技能目标:1. 学生能够运用所学知识,独立构建二叉排序树,并实现插入、删除和查找功能。
2. 学生能够分析二叉排序树的性能,对其进行优化,提高排序效率。
3. 学生能够运用二叉排序树解决实际问题,如数据排序、查找等。
情感态度价值观目标:1. 学生通过学习二叉排序树,培养对数据结构和算法的兴趣,提高解决问题的能力。
2. 学生在学习过程中,学会合作、交流,培养团队精神和共享意识。
3. 学生能够认识到二叉排序树在实际应用中的价值,激发对计算机科学的热爱。
本课程针对高中年级学生,课程性质为理论与实践相结合。
在教学过程中,注重启发式教学,引导学生主动探究、实践。
根据学生特点和教学要求,课程目标具体、可衡量,以便学生和教师能够清晰地了解课程的预期成果。
课程目标的分解为具体的学习成果,为后续的教学设计和评估提供依据。
二、教学内容1. 引入二叉排序树的概念,讲解其定义、性质和基本操作。
- 理解二叉树的基础知识,回顾二叉树的遍历方法。
- 介绍二叉排序树的定义,阐述其特点及应用场景。
- 分析二叉排序树的性质,如二叉排序树的中序遍历结果为有序序列。
2. 探讨二叉排序树的构建、插入、删除和查找操作。
- 讲解二叉排序树的构建方法,学会从无序数据建立二叉排序树。
- 分析插入、删除和查找操作的步骤,理解它们的时间复杂度。
- 举例说明如何利用二叉排序树实现数据排序和查找。
3. 分析二叉排序树的性能及优化方法。
- 探讨二叉排序树的高度、平衡因子等性能指标。
- 介绍常见的优化方法,如平衡二叉树(AVL树)和红黑树。
4. 实践环节:二叉排序树的应用。
- 设计实践题目,让学生动手实现二叉排序树的基本操作。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
数据结构课程设计:平衡二叉树目录1 课程设计的目的和内容..............................................1课程设计目的 ................................................ 1 1.11.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平衡因子:bf= TreeDepth(ldep)- TreeDepth(rdep)(2)程序主要功能模块求树深函数: TreeDepth()左(右)旋函数: L_Rotate(), R_Rotate()左右平衡函数: LeftBalance(), RightBalance()插入函数 : InsertAVL()前(中)序遍历: Preorder(), Inorder()输出二叉树函数 Output()(3)程序主要功能模块之间的调用插入函数InsertAVL(BSTNode* &T,int key)要调用左平衡函数LeftBalance()和右平衡函数RightBalance(),左右平衡函数要调用左旋函数R_Rotate()和右旋函数L_Rotate()(4)平衡二叉树不平衡形态分析1) LL 型:新结点 1 插在结点 3 的左孩子的左子树里。
调整方法见图2.1。
图中以结点2为轴心,将结点结点3从结点2 的右上方转到结点2 的右下侧,使结点 3成为结点2 的右孩子。
3 平衡二叉树3 221 31LL型图2.12)RR 型:新结点3 插在结点 1 的右孩子的右子树里。
调整方法见图2.2.2。
图中以结点 2 为轴心,将结点1 从结点2的左上方转到结点2 的左下侧,使结点1 的左孩子。
成为结点21221 33 RR型图2.23)LR 型:新结点 2 插在结点 3的左孩子的右子树里。
调整方法见图2.3 。
分为两步进行:第一步以结点 2 为轴心,将结点 1 从结点2 的左上方转到结点2 的左下侧,使结点1 成为结点2 的左孩子,结点 2 成为结点3的左孩子。
第二步跟 LL 型一样处理 ( 应以结点2为轴心 ) 。
4 平衡二叉树3 321 21 32 1LR型图2.34)RL 型:2 插在 1的右孩子的左子树里。
调整方法见图2.4 。
分为两步进行: 新结点第一步以结点2为轴心,将结点 3 从结点 2 的右上方转到结点 2 的右下侧,使结点3 成为结点2 的右孩子,结点 2成为结点 1的右孩子。
第二步跟 RR 型一样处理 ( 应以结点2 为轴心 ) 。
1 123 21 32 3RL型图2.45 平衡二叉树3 详细设计3.1 程序主要功能模块的伪代码算法(1)对以*p为根的二叉排序树作右旋处理void R_Rotate(BSTree &p) {BSTNode* lc;lc=p->lchild;p->lchild=lc->rchild;lc->rchild=p;p=lc;}对以*p为根的二叉排序树作左旋处理void L_Rotate(BSTree &p) {BSTNode* rc;rc=p->rchild;p->rchild=rc->lchild;rc->lchild=p;p=rc;}(2) 对以指针T所指结点为根的二叉排序树作左平衡旋转处理 void LeftBalance(BSTree &T) {int bf;BSTNode* lc;lc=T->lchild;bf = TreeDepth(lc->lchild) - TreeDepth(lc->rchild);switch(bf){case +1: //LLR_Rotate(T);break;case -1: //LRL_Rotate(T->lchild);6 平衡二叉树R_Rotate(T);}}对以指针T所指结点为根的二叉排序树作右平衡旋转处理 void RightBalance(BSTree &T){int bf;BSTNode* rc;rc=T->rchild;bf = TreeDepth(rc->lchild) - TreeDepth(rc->rchild);switch(bf){case -1: //RLL_Rotate(T);break;case +1: //RRR_Rotate(T->rchild);L_Rotate(T);}}(4)插入函数void InsertAVL(BSTNode* &T,int key){int bf;if(!T){T=(BSTNode*)malloc(sizeof(BSTNode));T->key=key;T->lchild=T->rchild=NULL;}else{if(key==T->key){printf("点已存在\n");7 平衡二叉树return;}else if(key<T->key) //*在*T的左子树中进行搜索{InsertAVL(T->lchild,key);bf = TreeDepth(T->lchild) - TreeDepth(T->rchild); if(bf>1)LeftBalance(T);}else //*在*T的右子树进行搜索{InsertAVL(T->rchild,key);bf = TreeDepth(T->lchild) - TreeDepth(T->rchild); if(bf<-1)RightBalance(T);}}}8 平衡二叉树3.2 程序主要流程图开始2 3switch(choice)1Preorder(T) Inorder(T)InsertAVL(T,key)输入keyNT==NULL 结束Y 0 InsertAVL(T,key)T->key=key switch(choice)key==T->keyNY Nkey<T->key 点已存在YInsertAVL(T->lchild,key) Bf>1>InsertAVL(T->rchild,key) LeftBalance(T)RightBalance(T) Bf<-1 >9 平衡二叉树4 测试数据与测试结果图4-1 程序主界面图4-2 退出程序10 平衡二叉树图4-3 LL型11 平衡二叉树图4-4 LR型12 平衡二叉树图4-5 RR型13 平衡二叉树图4-6 RL型14 平衡二叉树5 程序的使用和改进5.1 用户使用说明(1)本程序调用时当按1时,进入插入操作,每输入一个元素就把它插入到二叉树中,然后进行左平衡,右平衡的判断,重新把二叉树变为平衡二叉树。
平衡二叉树的显示输出为输出根结点后根接着输出的上层为左子树,下层为右子树。
(2)当选择2时,进行平衡二叉树的前序遍历。
(3)当选择3时,进行平衡二叉树的中序遍历。
(4)若插入好二叉树后,选择4清屏,原来插入的二叉树结点数据仍然保留,继续插入需要注意不要插入已经存在的结点.(5)选择0退出程序5.2 程序的改进(1)可以加入平衡二叉树的删除操作;(2)可以加入平衡二叉树的查找操作;(3)这次课程设计没有找到很好的显示平衡二叉树的方式,选用的显示方式不是很直观。
15 平衡二叉树6 课程设计小结这次数据结构课程设计是平衡二叉树相关,通过课程设计对二叉排序树有了更进一步的深入了解以及平衡二叉树的四种不平衡形态的分析,处理四种不平衡形态(LL,LR,RL,RR)的方式,通过左旋及右旋函数实现左平衡和右平衡,并验证了其中序序列有序性~这次课程设计主要的思想就是递归,首先是插入函数的递归,判断所要插入的数据跟原来树的根结点比较,比根结点数据小,则递归调用插入函数继续在其左子树中插入,比根结点的数据大,则递归调用插入函数继续在其右子树中插入,直到找到合适的位置,则插入成功。
插入成功后返回上一层次的递归,并且求出相当于插入结点的双亲结点的平衡因子,依次返回,找到第一个不平衡的结点,再做相应的调整,重复上述过程,直到整个二叉树都平衡。