大数据结构 平衡二叉树的操作演示
数据结构二叉树PPT课件

A
B
CX
E FGH I
J
8
四. 基本名词术语
1. 结点的度:该结点拥有的子树的数目。
2. 树的度:树中结点度的最大值。
3. 叶结点:度为0 的结点. 4. 分支结点: 度非0 的结点. 5. 层次的定义: 根结点为第一层,若某结点在第i 层,
则其孩子结点(若存在)为第i+1层.
A
第1层
B
CX
第2层
12
完全二叉树.
三.i 层最多有2i–1个结点(i1)。
2. 深度为h 的非空二叉树最多有2h -1个结点.
3. 若非空二叉树有n0个叶结点,有n2个度为2的结点,
则
n0=n2+1
4. 具有n个结点的完全二叉树的深度h=log2n+1.
13
二叉树的存储结构
39
例
A
BC D
E F GH I
对树进行先根遍历,获得的先根序列是: ABEFCDGHI
对树进行后根遍历,获得的后根序列是: EFBCGHIDA
40
2.森林的遍历
先序遍历(对森林中的每一棵树进行先根遍历)
1)若森林不空,访问森林中第一棵树的根结点; 2)先序遍历森林中第一棵树的子树森林; 3)先序遍历森林中(除第一棵树外)其余树构成的森林。
(空) 根 根 根
根
左 子 树
右 子 树
左 子 树
右 子 树
11
二. 两种特殊形态的二叉树
1. 满二叉树
若一棵二叉树中的结点, 或者为叶结点, 或者具有两 棵非空子树,并且叶结点都集 中在二叉树的最下面一层.这 样的二叉树为满二叉树.
2.完全二叉树
若一棵二叉树中只有最下 面两层的结点的度可以小于2, 并且最下面一层的结点(叶结 点)都依次排列在该层从左至 右的位置上。这样的二叉树为
详解平衡二叉树

一、平衡二叉树的概念平衡二叉树(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结点的位置。
数据结构与算法—二叉排序树详解

数据结构与算法—二叉排序树详解前言前面介绍学习的大多是线性表相关的内容,把指针搞懂后其实也没有什么难度。
规则相对是简单的。
再数据结构中树、图才是数据结构标志性产物,(线性表大多都现成api可以使用),因为树的难度相比线性表大一些并且树的拓展性很强,你所知道的树、二叉树、二叉排序树,AVL树,线索二叉树、红黑树、B数、线段树等等高级数据结构。
然而二叉排序树是所有的基础,所以彻底搞懂二叉排序树也是非常重要的。
树参考王道数据结构二叉树也是树的一种,而二叉排序树又是二叉树的一种。
•树是递归的,将树的任何一个节点以及节点下的节点都能组合成一个新的树。
并且很多操作基于递归完成。
•根节点:最上面的那个节点(root),根节点没有前驱节点,只有子节点(0个或多个都可以)•层数:一般认为根节点是第1层(有的也说第0层)。
而树的高度就是层数最高(上图层数开始为1)节点的层数•节点关系:父节点:就是链接该节点的上一层节点,孩子节点:和父节点对应,上下关系。
而祖先节点是父节点的父节点(或者祖先)节点。
兄弟节点:拥有同一个父节点的节点们!•度:节点的度就是节点拥有孩子节点的个数(是孩子不是子孙).而树的度(最大)节点的度。
同时,如果度大于0就成为分支节点,度等于0就成为叶子节点(没有子孙)。
相关性质:•树的节点数=所有节点度数 1.•度为m的树第i层最多有mi-1个节点。
(i>=1)•高度而h的m叉树最多(mh-1)/(m-1)个节点(等比数列求和) •n个节点的m叉树最小高度[logm(n(m-1) 1)]二叉树二叉树是一树的一种,但应用比较多,所以需要深入学习。
二叉树的每个节点最多只有两个节点。
二叉树与度为2的树的区别:•一:度为2的的树必须有三个节点以上,二叉树可以为空。
•二:二叉树的度不一定为2:比如说斜树。
•三:二叉树有左右节点区分,而度为2的树没有左右节点的区分。
几种特殊二叉树:•满二叉树。
高度为n的满二叉树有2n-1个节点•完全二叉树:上面一层全部满,最下一层从左到右顺序排列•二叉排序树:树按照一定规则插入排序(本文详解)。
数据结构—树二叉树前序遍历、中序遍历、后序遍历【图解实现】

数据结构—树二叉树前序遍历、中序遍历、后序遍历【图解实现】AI研习图书馆,发现不一样的精彩世界数据结构二叉树的遍历一、树在谈二叉树的知识点之前,我们首先来看一下树和图的基本概念。
树:不包含回路的连通无向图,树是一种简单的非线性结构。
由于树有一个不包含回路的特点,因此树被赋予了许多特性,如下所示:1、一棵树中任意的两个结点有且仅有唯一的一条路径连通2、一棵树如果有n个结点,那么它一定恰好有n-1条边3、在一棵树中加上一条边,将会构成一个回路4、一棵树中有且仅有一个没有前驱的结点,即为根结点通常情况下,我们在对树进行讨论的时候,将一棵树中的每个点称为结点:根结点:没有父结点的结点叶结点:没有子结点的结点内部结点:一个结点既不是根结点也不是叶结点每个结点有一个深度的概念,例如上图左边的树,4号结点深度是3。
二、二叉树1. 基本概念二叉树是一种非线性结构,二叉树是由递归定义的,其结点有左右子树之分。
2. 二叉树的存储结构二叉树一般采用链式存储结构,存储结点由数据域和指针域组成,二叉树的链式存储结构也称为二叉链表。
指针域:左指针域和右指针域特点:1、每个结点最多有两颗子树2、左子树和右子树是有顺序的,次序不能颠倒3、即使某个结点只有一颗子树,也要区分左右子树4、二叉树可为空,空的二叉树没有结点,非空二叉树有且仅有一个根节点二叉树中有两种比较特殊的二叉树:满二叉树、完全二叉树,对于满二叉树和完全二叉树可以按照层次进行顺序存储。
满二叉树:二叉树中每个内部结点都存在左子树和右子树满二叉树一定是完全二叉树,但完全二叉树不一定是满二叉树。
满二叉树的严格定义:一颗深度为h且具有2h-1个结点的二叉树。
完全二叉树:解释一:如果一颗二叉树除了最右边位置上有一个或几个叶结点缺少外,其他都是丰满的,那么这样的二叉树就是完全二叉树。
解释二:除第h层外,其他各层(1到h-1)的结点数都达到最大个数,第h层从右向左连续缺若干结点,则这个二叉树就是完全二叉树。
平衡二叉树操作演示.doc

平衡二叉树操作演示.数据结构实习报告题目:平衡二叉树的操作演示班级:信息管理与信息系统11-平衡二叉树的操作演示班级:信息管理与信息系统11:崔佳学号:201101050903完成日期:2013.06.25一、需求分析1. 初始,平衡二叉树为空树,操作界面给出两棵平衡二叉树的显示、查找、插入、删除、销毁、合并两棵树,几种选择。
其中查找、插入和删除操作均要提示用户输入关键字。
每次插入或删除一个节点后都会更新平衡二叉树的显示。
2. 平衡二叉树的显示采用凹入表形式。
3.每次操作完毕后都会给出相应的操作结果,并进入下一次操作,知道用户选择退出二、概要设计1.平衡二叉树的抽象数据类型定义:ADT BalancedBinaryTree{ 数据对象D:D是具有相同特性的数据元素的集合。
各个数据元素均含有类型相同,可唯一标志的数据元素的关键字。
数据关系R:数据元素同属一个集合。
基本操作P:InitA VL(BSTree T) 操作结果:构造一个空的平衡二叉树T DestroyA VL(BSTree T) 初始条件:平衡二叉树T存在操作结果:销毁平衡二叉树T SearchA VL(BSTree T,int key) 初始条件:平衡二叉树T存在,key为和关键字相同类型的给定值操作结果:若T中存在关键字和key相等的数据元素,则返回指向该元素的指针,否则为空InsertA VL(BSTree T,int key,Status taller) 初始条件:平衡二叉树T存在,key和关键字的类型相同操作结果:若T中存在关键字等于key的数据元素则返回,若不存在则插入一个关键字为key的元素DeleteA VL(BSTree T,int key,Status lower) 初始条件:平衡二叉树T存在,key和关键字的类型相同操作结果:若T中存在关键字和key相同的数据元素则删除它}ADT BalancedBinaryTree2.本程序包含二个模块1)主程序模块:void main(){ 接收命令;While(“命令”!=“退出”){ 处理命令;清屏并得新打印提示信息;接收下一条命令;}}2)平衡二叉树基本操作实现平衡二叉树的抽象数据类型的各函数原型。
浙教版(2019)2022—2023学年高中信息技术选修1《二叉树的基本操作》教学PPT课件

self.right=right #右子树
代 码 实 现
if __name__=='__main__’:
二
root=Node('A',Node('B',Node('D'),Node('E')),Node('C',rigt=Node('F',Node('G'
叉
)))
树
print("前序遍历:")
preTraverse(root)
afterTraverse(____ro__o_t_.r_i_g_h_t_) print(____r_o_o_t_.v__a_lu__e_)
谢谢观看!
二叉树的基本操作
浙教版(2019)高中信息技术选修1
PART
02
二叉树的基本操作
Click here to add your title
树Hale Waihona Puke 实现树的遍历满二叉树
节点个数为7=23-1
满二叉树是完全二叉树, 完全二叉树不一定是满 二叉树。
完全二叉树
节点个数为10<24-1
1.每个节点的度均为2或0 2. 每一层上的结点数都达 到最大值
有唯一二叉树: 前序遍历+中序遍历 后序遍历+中序遍历
前序遍历+后序遍历 -----没有唯一二叉树
二叉树的基本操作
·二叉树的唯一性
例如:前序遍历:E-A-C-B-D-G-F 中序遍历:A-B-C-D-E-F-G
求其后序遍历顺序?
先画出二叉树,再用后序遍历规 则求出其输出顺序
后序遍历:B-D-C-A-F-G-E
平衡二叉树的定义及基本操作(查找、插入、删除)及代码实现

平衡⼆叉树的定义及基本操作(查找、插⼊、删除)及代码实现⽂章⽬录平衡⼆叉树的定义 为了避免树的⾼度增长过快,降低⼆叉排序树的性能,我们规定在插⼊和删除⼆叉树结点时,要保证在任意结点的左、右⼦树⾼度差的绝对值不超过1,将这样的树称为平衡⼆叉树(Balanced Binary Tree),简称平衡树(AVL)。
此外,AVL树⼜称为⾼度平衡的⼆叉查找树。
定义结点左⼦树与右⼦树的⾼度差为该结点的平衡因⼦,则平衡⼆叉树结点的平衡因⼦的值只可能是-1,0或1 。
平衡⼆叉树可定义为:或者是⼀棵空树,或者是具有下列性质的⼆叉树:它的左⼦树和右⼦树都是平衡⼆叉树,且左⼦树和右⼦树的⾼度差的绝对值不超过1。
平衡⼆叉树的结点类型描述:typedef struct AVLNode{int data;//数据域int bf;//平衡因⼦struct AVLNode *lchild,*rchild;//指针域}AVLNode,*AVLTree;平衡⼆叉树的查找 平衡⼆叉树上进⾏查找的过程与⼆叉排序树相同,详细完整代码请参照。
因此,在查找过程中,与给定值进⾏⽐较的关键字个数不超过树的深度。
可以证明,含有n个结点的平衡⼆叉树的最⼤深度为O(log n),因此平衡⼆叉树的平均查找长度为O(log n)。
22平衡⼆叉树的平衡旋转 ⼆叉排序树保证平衡的基本思想如下: 每当在⼆叉排序树中插⼊(或删除)⼀个结点时,⾸先检查其插⼊路径上的结点是否因为此次操作导致了不平衡。
若导致了不平衡,则先找到插⼊路径上离插⼊结点最近的平衡因⼦的绝对值⼤于1的结点A,再对以A为根的⼦树,在保持⼆叉排序树特性的前提下,调整各结点的位置关系,使之重新达到平衡。
⼀般可将失去平衡后进⾏调整的规律归纳为下列四种情况:LL平衡旋转,RR平衡旋转,LR平衡旋转,RL平衡旋转。
LL平衡旋转(右单旋转) 由于在结点A的左孩⼦(L)的左⼦树(L)上插⼊了新结点,A的平衡因⼦由1增⾄2,导致了以A为根的⼦树失去平衡。
平衡二叉树(AVL树)的基本操作(附有示意图)

平衡二叉树关于树的深度是平衡的,具有较高的检索效率。
平衡二叉树或是一棵空树,或是具有下列性质的二叉排序树:其左子树和右子树都是平衡二叉树,而且左右子树深度之差绝对值不超过1. 由此引出了平衡因子(balance factor)的概念,bf定义为该结点的左子树的深度减去右子树的深度(有些书是右子树深度减去左子树深度,我是按照左子树减去右子树来计算的,下面的代码也是这样定义的),所以平衡二叉树的结点的平衡因子只可能是-1,0,1 ,某个结点的平衡因子绝对值大于1,该二叉树就不平衡。
平衡二叉树在出现不平衡状态的时候,要进行平衡旋转处理,有四种平衡旋转处理(单向右旋处理,单向左旋处理,双向旋转(先左后右)处理,双向旋转(先右后左)处理),归根到底是两种(单向左旋处理和单向右旋处理)。
文件"tree.h"view plain1.#include<iostream>2.#include<stack>3.#include<queue>ing namespace std;5.6.const int LH=1; //左子树比右子树高17.const int EH=0; //左右子树一样高8.const int RH=-1;//右子树比左子树高19.const int MAX_NODE_NUM=20; //结点数目上限10.11.class AVL_Tree;12.13.class AvlNode14.{15.int data;16.int bf; //平衡因子17. AvlNode *lchild;18. AvlNode *rchild;19.friend class AVL_Tree;20.};21.22.class AVL_Tree23.{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<<"平衡树为空"<<endl;44. T=NULL;45.return;46. }47.48.int k=i;49.bool taller=false;50.for(i=0;i<k;i++)51. Insert_Avl(T,num[i],taller);//逐个进行插入,插入过程看下面的示意图52. cout<<"_____建树完成____"<<endl;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的新结点,并返回true148.//若因为插入而使得二叉排序树失去平衡,则做平衡旋转处理149.//taller反映树是否长高150.151.if(!T)152. {153.//插入新结点,树长高,taller为true154. 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<T->data) //继续在T的左子树中进行搜索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.else204.//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.else251. {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结点即可。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
平衡二叉树操作的演示1.需求分析本程序是利用平衡二叉树,实现动态查找表的基本功能:创建表,查找、插入、删除。
具体功能:(1)初始,平衡二叉树为空树,操作界面给出创建、查找、插入、删除、合并、分裂六种操作供选择。
每种操作均提示输入关键字。
每次插入或删除一个结点后,更新平衡二叉树的显示。
(2)平衡二叉树的显示采用凹入表现形式。
(3)合并两棵平衡二叉树。
(4)把一棵二叉树分裂为两棵平衡二叉树,使得在一棵树中的所有关键字都小于或等于x,另一棵树中的任一关键字都大于x。
如下图:2.概要设计平衡二叉树是在构造二叉排序树的过程中,每当插入一个新结点时,首先检查是否因插入新结点而破坏了二叉排序树的平衡性,若是则找出其中的最小不平衡子树,在保持二叉排序树特性的前提下,调整最小不平衡子树中各结点之间的关系,进行相应的旋转,使之成为新的平衡子树。
具体步骤:(1)每当插入一个新结点,从该结点开始向上计算各结点的平衡因子,即计算该结点的祖先结点的平衡因子,若该结点的祖先结点的平衡因子的绝对值不超过1,则平衡二叉树没有失去平衡,继续插入结点;(2)若插入结点的某祖先结点的平衡因子的绝对值大于1,则找出其中最小不平衡子树的根结点;(3)判断新插入的结点与最小不平衡子树的根结点个关系,确定是那种类型的调整;(4)如果是LL型或RR型,只需应用扁担原理旋转一次,在旋转过程中,如果出现冲突,应用旋转优先原则调整冲突;如果是LR型或RL型,则需应用扁担原理旋转两次,第一次最小不平衡子树的根结点先不动,调整插入结点所在子树,第二次再调整最小不平衡子树,在旋转过程中,如果出现冲突,应用旋转优先原则调整冲突;(5)计算调整后的平衡二叉树中各结点的平衡因子,检验是否因为旋转而破坏其他结点的平衡因子,以及调整后平衡二叉树中是否存在平衡因子大于1的结点。
流程图3.详细设计二叉树类型定义:typedefint Status;typedefintElemType;typedefstructBSTNode{ElemType data;int bf;structBSTNode *lchild ,*rchild;} BSTNode,* BSTree;Status SearchBST(BSTreeT,ElemType e)//查找void R_Rotate(BSTree&p)//右旋void L_Rotate(BSTree&p)//左旋void LeftBalance(BSTree&T)//插入平衡调整void RightBalance(BSTree&T)//插入平衡调整Status InsertAVL(BSTree&T,ElemTypee,int&taller)//插入void DELeftBalance(BSTree&T)//删除平衡调整void DERightBalance(BSTree&T)//删除平衡调整Status Delete(BSTree&T,int&shorter)//删除操作Status DeleteAVL(BSTree&T,ElemTypee,int&shorter)//删除操作void merge(BSTree&T1,BSTree &T2)//合并操作void splitBSTree(BSTreeT,ElemTypee,BSTree&T1,BSTree &T2)//分裂操作void PrintBSTree(BSTree&T,intlev)//凹入表显示附录源代码:#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//二叉类型树的类型定义typedefint Status;typedefintElemType;typedefstructBSTNode{ElemType data;int bf;//结点的平衡因子structBSTNode *lchild ,*rchild;//左、右孩子指针} BSTNode,* BSTree;/*查找算法*/Status SearchBST(BSTreeT,ElemType e){if(!T){return 0; //查找失败}else if(e == T->data ){return 1; //查找成功}else if (e < T->data){returnSearchBST(T->lchild,e);}else{returnSearchBST(T->rchild,e);}}//右旋voidR_Rotate(BSTree&p){BSTreelc; //处理之前的左子树根结点lc = p->lchild; //lc指向的*p的左子树根结点p->lchild = lc->rchild; //lc的右子树挂接为*P的左子树lc->rchild = p;p = lc; //p指向新的根结点}//左旋voidL_Rotate(BSTree&p){BSTreerc;rc = p->rchild; //rc指向的*p的右子树根结点p->rchild = rc->lchild; //rc的左子树挂接为*p的右子树rc->lchild = p;p = rc; //p指向新的根结点}//对以指针T所指结点为根结点的二叉树作左平衡旋转处理,//本算法结束时指针T指向新的根结点voidLeftBalance(BSTree&T){BSTreelc,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作右旋平衡处理}}//右平衡旋转处理voidRightBalance(BSTree&T){BSTreerc,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;case RH: T->bf = EH; rc->bf=LH;break;}ld->bf=EH;R_Rotate(T->rchild);L_Rotate(T);}}//插入结点Status InsertAVL(BSTree&T,ElemTypee,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)){}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){//删除平衡调整BSTreelc,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) //删除平衡调整{BSTreerc,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);}}voidSDelete(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,ElemTypee,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(BSTreeT,ElemTypee,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);}//分裂voidsplitBSTree(BSTreeT,ElemTypee,BSTree&T1,BSTree &T2){ BSTree t1 = NULL,t2 = NULL;split(T,e,t1,t2);T1 = t1;T2 = t2;return;}//构建voidCreatBSTree(BSTree&T){intnum,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();}//凹入表形式显示方法voidPrintBSTree(BSTree&T,intlev){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){intcho,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);}。