实现平衡二叉排序树的各种算法代码 一

合集下载

数据结构平衡二叉树的操作演示

数据结构平衡二叉树的操作演示

平衡二叉树操作的演示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{ElemType data;int bf;struct BSTNode *lchild ,*rchild;} BSTNode,* BSTree;Status SearchBST(BSTree T,ElemType e)//查找void R_Rotate(BSTree &p)//右旋void L_Rotate(BSTree &p)//左旋void LeftBalance(BSTree &T)//插入平衡调整void RightBalance(BSTree &T)//插入平衡调整Status InsertAVL(BSTree &T,ElemType e,int &taller)//插入void DELeftBalance(BSTree &T)//删除平衡调整void DERightBalance(BSTree &T)//删除平衡调整Status Delete(BSTree &T,int &shorter)//删除操作Status DeleteAVL(BSTree &T,ElemType e,int &shorter)//删除操作void merge(BSTree &T1,BSTree &T2)//合并操作void splitBSTree(BSTree T,ElemType e,BSTree &T1,BSTree &T2)//分裂操作void PrintBSTree(BSTree &T,int lev)//凹入表显示附录源代码:#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//二叉类型树的类型定义typedef int Status;typedef int ElemType;typedef struct BSTNode{ElemType data;int bf;//结点的平衡因子struct BSTNode *lchild ,*rchild;//左、右孩子指针} BSTNode,* BSTree;/*查找算法*/Status SearchBST(BSTree T,ElemType e){if(!T){return 0; //查找失败}else if(e == T->data ){return 1; //查找成功}else if (e < T->data){return SearchBST(T->lchild,e);}else{return SearchBST(T->rchild,e);}}//右旋void R_Rotate(BSTree &p){BSTree lc; //处理之前的左子树根结点lc = p->lchild; //lc指向的*p的左子树根结点p->lchild = lc->rchild; //lc的右子树挂接为*P的左子树lc->rchild = p;p = lc; //p指向新的根结点}//左旋void L_Rotate(BSTree &p){BSTree rc;rc = p->rchild; //rc指向的*p的右子树根结点p->rchild = rc->lchild; //rc的左子树挂接为*p的右子树rc->lchild = p;p = rc; //p指向新的根结点}//对以指针T所指结点为根结点的二叉树作左平衡旋转处理,//本算法结束时指针T指向新的根结点void LeftBalance(BSTree &T){BSTree lc,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作右旋平衡处理}}//右平衡旋转处理void RightBalance(BSTree &T){BSTree rc,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;break;case RH: T->bf = EH; rc->bf=LH;break;}ld->bf=EH;R_Rotate(T->rchild);L_Rotate(T);}}//插入结点Status InsertAVL(BSTree &T,ElemType e,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)){return 0;}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){//删除平衡调整BSTree lc,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) //删除平衡调整{BSTree rc,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);}}void SDelete(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,ElemType e,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(BSTree T,ElemType e,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);}//分裂void splitBSTree(BSTree T,ElemType e,BSTree &T1,BSTree &T2){ BSTree t1 = NULL,t2 = NULL;split(T,e,t1,t2);T1 = t1;T2 = t2;return;}//构建void CreatBSTree(BSTree &T){int num,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();}//凹入表形式显示方法void PrintBSTree(BSTree &T,int lev){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){int cho,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);}。

平衡二叉树

平衡二叉树
1 1 0 0 0 1 0 0 (a) 平衡二叉树 -1 -1 1
2 -1 0 0 0
-1
-2 0 0 1
0 0
1
(b) 不平衡二叉树 图9.6 平衡与不平衡二叉树及结点的平衡因子
平衡二叉树是二叉排序树的另一种形式. 平衡二叉树 我们希望由任何初始序列构成的二叉排序 树都是平衡二叉树 平衡二叉树.因为平衡二叉树 平衡二叉树上任 平衡二叉树 平衡二叉树 1 何结点的左右子树的深度之差都不超过1, 则可以证明它的深度和logN是同数量级的 (其中N是结点的个数).由此,它的平 均查找长度也和logN同数量级.
typedef structBSTNode { ElemType data; int bf; //结点的平衡因子 结点的平衡因子 struct BSTNode *lchild, *rchild; //左,右孩子指针 左 } BSTNode, * BSTree;
算法9.7如下: 算法 如下: 如下 void R_Rotate (BSTree &p) { //对以 为根的二叉排序树作右旋处理,处理之后p指向新的树根结点, 对以*p为根的二叉排序树作右旋处理,处理之后 指向新的树根结点, 对以 为根的二叉排序树作右旋处理 指向新的树根结点 //即旋转处理之前的左子树的根结点 即旋转处理之前的左子树的根结点 lc = p->lchild; //lc指向的 的左子树根结点 指向的*p的左子树根结点 - 指向的 p->lchild = lc->rchild; //lc的右子树挂接为 的左子树 的右子树挂接为*p的左子树 - - 的右子树挂接为 lc->rchild = p; - p = lc; //p指向新的根结点 指向新的根结点 } // R_Rotate

平衡二叉树

平衡二叉树
#define EH 0 //等高
#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树体现了一种平衡的美感,两种旋转是互为镜像的,插入删除是互为镜像的操作,没理由会有那么大的差别。实际上,平衡化可以统一的这样来操作:

数据结构二叉排序树

数据结构二叉排序树

05
13
19
21
37
56
64
75
80
88
92
low mid high 因为r[mid].key<k,所以向右找,令low:=mid+1=4 (3) low=4;high=5;mid=(4+5) div 2=4
05
13
19
low
21
37
56
64
75
80
88
92
mid high
因为r[mid].key=k,查找成功,所查元素在表中的序号为mid 的值
平均查找长度:为确定某元素在表中某位置所进行的比 较次数的期望值。 在长度为n的表中找某一元素,查找成功的平均查找长度:
ASL=∑PiCi
Pi :为查找表中第i个元素的概率 Ci :为查到表中第i个元素时已经进行的比较次数
在顺序查找时, Ci取决于所查元素在表中的位置, Ci =i,设每个元素的查找概率相等,即Pi=1/n,则:
RL型的第一次旋转(顺时针) 以 53 为轴心,把 37 从 53 的左上转到 53 的左下,使得 53 的左 是 37 ;右是 90 ,原 53 的左变成了 37 的右。 RL型的第二次旋转(逆时针)
一般情况下,假设由于二叉排序树上插入结点而失去 平衡的最小子树的根结点指针为a(即a是离插入结点最 近,且平衡因子绝对值超过1的祖先结点),则失去平衡 后进行调整的规律可归纳为下列四种情况: ⒈RR型平衡旋转: a -2 b -1 h-1 a1
2.查找关键字k=85 的情况 (1) low=1;high=11;mid=(1+11) / 2=6
05
13
19
21

二叉排序树c语言代码实现

二叉排序树c语言代码实现
printf ("是否继续输入?\n 1.是 2.否(其他键 退出)\n");
if ((*n) != NULL) {
free (*n);
*n = NULL;
}
}
/* 查找结点 */
PNODE find_node (PNODE n, int value) {
in_order_traversal ( n->right);
}
}
int main() {
char buf[50],a[1000];
int i,n,option,s[80],p;
PNODE tree = NULL;/*树的第一个结点*/
PNODE node = NULL;
{
r = (PNODE)malloc(sizeof(NODE));
if(!r)
{
printf("内存分配失败!");
exit(0);
zjm3:fgets (buf, sizeof(buf), stdin);
sscanf (buf, "%i", &option);
printf ("\n\n");
if(option<0) {
printf ("输入错误,请重新输入该元素\n",n);
goto zjm3;}
if(find_node (tree, option))
{
(*n)->value = value;
(*n)->left = NULL;
(*n)->right = NULL;
}
}

数据结构:第9章 查找2-二叉树和平衡二叉树

数据结构:第9章 查找2-二叉树和平衡二叉树
NODE *t; char x; {if(t==NULL)
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

数据结构 -第12周查找第3讲-二叉排序树.pdf

数据结构 -第12周查找第3讲-二叉排序树.pdf

以二叉树或树作为表的组织形式,称为树表,它是一类动态查找表,不仅适合于数据查找,也适合于表插入和删除操作。

常见的树表:二叉排序树平衡二叉树B-树B+树9.3.1 二叉排序树二叉排序树(简称BST)又称二叉查找(搜索)树,其定义为:二叉排序树或者是空树,或者是满足如下性质(BST性质)的二叉树:❶若它的左子树非空,则左子树上所有节点值(指关键字值)均小于根节点值;❷若它的右子树非空,则右子树上所有节点值均大于根节点值;❸左、右子树本身又各是一棵二叉排序树。

注意:二叉排序树中没有相同关键字的节点。

二叉树结构满足BST性质:节点值约束二叉排序树503080209010854035252388例如:是二叉排序树。

66不试一试二叉排序树的中序遍历序列有什么特点?二叉排序树的节点类型如下:typedef struct node{KeyType key;//关键字项InfoType data;//其他数据域struct node*lchild,*rchild;//左右孩子指针}BSTNode;二叉排序树可看做是一个有序表,所以在二叉排序树上进行查找,和二分查找类似,也是一个逐步缩小查找范围的过程。

1、二叉排序树上的查找Nk< bt->keybtk> bt->key 每一层只和一个节点进行关键字比较!∧∧p查找到p所指节点若k<p->data,并且p->lchild=NULL,查找失败。

若k>p->data,并且p->rchild=NULL,查找失败。

查找失败的情况加上外部节点一个外部节点对应某内部节点的一个NULL指针递归查找算法SearchBST()如下(在二叉排序树bt上查找关键字为k的记录,成功时返回该节点指针,否则返回NULL):BSTNode*SearchBST(BSTNode*bt,KeyType k){if(bt==NULL||bt->key==k)//递归出口return bt;if(k<bt->key)return SearchBST(bt->lchild,k);//在左子树中递归查找elsereturn SearchBST(bt->rchild,k);//在右子树中递归查找}在二叉排序树中插入一个关键字为k的新节点,要保证插入后仍满足BST性质。

平衡二叉树调整算法

平衡二叉树调整算法

平衡二叉树调整算法在平衡二叉树中插入一个结点后造成不平衡,设最低的不平衡结点为A,并已知A的左孩子平衡因子为0,右孩子平衡因子为1,则应该做(C)型调整以使其平衡A LLB LRC RLD RR若向平衡二叉树中插入一个新结点后破坏了平衡二叉树的平衡性。

首先要找出插入新结点后失去平衡的最小子树根结点的指针。

然后再调整这个子树中有关结点之间的链接关系,使之成为新的平衡子树。

当失去平衡的最小子树被调整为平衡子树后,原有其他所有不平衡子树无需调整,整个二叉排序树就又成为一棵平衡二叉树。

失去平衡的最小子树是指以离插入结点最近,且平衡因子绝对值大于 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 结点的位置。

即先使之成为LL型,再按LL型处理。

如图中所示,即先将圆圈部分先调整为平衡树,然后将其以根结点接到 A 的左子树上,此时成为LL 型,再按LL 型处理成平衡型。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

实现平衡二叉排序树的各种算法代码一/* 《实现平衡二叉排序树的各种算法》一、分析题目要求用函数实现如下平衡二叉排序树算法,:(1)插入新结点(2)前序、中序、后序遍历二叉树(递归)(3)前序、中序、后序遍历的非递归算法(4)层次遍历二叉树(5)在二叉树中查找给定关键字(函数返回值为成功1,失败0)(6)交换各结点的左右子树(7)求二叉树的深度(8)叶子结点数(9)删除某结点为了完成以上的各项操作,首先应该用函数建一棵平衡二叉排序树,输入形式是首先输入要建的二叉树的结点数,然后依次输入各个结点的值。

在实现插入新结点的函数时,需要一个向一棵二叉树插入新结点的函数。

可用递归算法写出平衡二叉树的前序,中序,后序遍历的函数。

在写平衡二叉树的前,中,后序遍历的非递归算法时要用到栈结构的知识,运用栈结构来存储平衡二叉树结点的指针。

在层次遍历二叉树时需要用到队列结构,运用队列结构的先进先出来存储二叉树的结点指针。

在遍历二叉树的结点时需要一个访问结点数据的函数。

二叉树是一棵排序树,所以二叉树的查找可以运用其有序的性质,查找的方式和建树的方式相似。

交换二叉树各结点的左右子树时,可以用先序遍历递归的方式从根结点向下递归,每次访问结点时就需将各结点的左右孩子的指针调换,并对该结点的平衡因子作相应的处理。

示二叉树的深度时,可用递归的方式访问结点的左右子树,并记录下左右子树的深度,最后返回左右子树中较深的深度的值即可。

可以用一次遍历的方式遍历二叉树,记录每一个经过的结点,若结点存在且左右孩子都为空,则该结点为叶子结点。

删除二叉树的某个结点时,首先要写一个函数,用递归查找的方式找到相应的结点,该函数还要有调整二叉树平衡的作用,因为若删除结点使得二叉树深度减少而不平衡,需要调整二叉树的平衡,若该结点不存在则返回ERROR,,若存在该结点,则应该再写一个函数来删除该结点,在删除之前还要判断该结点是只有左子树还是只有右子树还是左右子树都有的情况:若只有左或是只有右子树,则只需删除该结点,并回溯调整二叉树的平衡;若该结点的左右子树都有,则应该用另一个函数递归找到该结点的直接“后继”,并从该“后继”开始回溯调整二叉树的平衡。

*/#include&lt;stdio.h&gt;#include&lt;stdlib.h&gt;#include&lt;malloc.h&gt;#define OK 1#define ERROR 0#define EH 0#define RH -1#define EQ(a,b) ((a)==(b))#define LT(a,b) ((a)&lt;(b))#define LQ(a,b) ((a)&lt;=(b))#define STACK_INIT_SIZE 100 // 栈#define STACKINCREMENT 10 // 栈#define MAXQSIZE 100 //队列#define ElemType int#define Status int#define TRUE 1#define FALSE 0#define Boolean bool//-----------------------------------------结构体typedef struct BSTNode//平衡二叉树结构{ElemType data;int bf;struct BSTNode *lchild,*rchild;}BSTNode,*BSTree;typedef BSTree SElemType; //栈typedef BSTree QElemType; //队列typedef struct //队列的结构体{QElemType *base;int front;int rear;}SqQueue;typedef struct SqStack //栈的结构体{SElemType *base;SElemType *top;}SqStack;//-------------------------------------函数列表//队列Status InitQueue(SqQueue &amp;Q); //初始化队列Status EnQueue(SqQueue &amp;Q,QElemType e); //进队列Status DeQueue(SqQueue &amp;Q,QElemType &amp;e); //出队列Status GetHead(SqQueue Q,QElemType &amp;e); //获队列首int QueueLength(SqQueue Q); //队列长度Status QueueTraverse(SqQueue Q); //遍历队列//栈Status InitStack(SqStack &amp;S); //初始化栈Status Push(SqStack &amp;S,SElemType e); //进栈Status Pop(SqStack &amp;S,SElemType &amp;e); //出栈Status GetTop(SqStack S,SElemType &amp;e); //获栈顶int StackLength(SqStack S); //栈的长度Status StackEmpty(SqStack S); //判栈空Status StackTraverse(SqStack S); //栈的遍历//平衡二叉树void R_Rotate(BSTree &amp;p); //右旇void L_Rotate(BSTree &amp;p); //左旇Status InsertAVL(BSTree &amp;T,ElemType e,Boolean &amp;taller);//平衡二叉树结点插void LeftBalance(BSTree &amp;T); //左平衡void RigthBalance(BSTree &amp;T); //右平衡Status CreateBST(BSTree &amp;T,int n); //建树Status Visit(ElemType e); //访问Status PreOrderTraverse(BSTree T); //前序遍历Status InOrderTraverse(BSTree T); //中序遍历Status PostOrderTraverse(BSTree T); //后序遍历Status preOrderIter(BSTree T); //前序非递归遍历Status inOrderIter(BSTree T); //中序非递归遍历Status postOrderIter(BSTree T); //后序非递归遍历Status FindBST(BSTree T,ElemType key,int &amp;n);//在二叉树中查找关键词Status OverTraverse(BSTree &amp;T); //层次遍历Status OverChang(BSTree &amp;T); //交换左右子树int BSTDeep(BSTree T); //求树的深度Status Sum(BSTree T,int &amp;n); //求叶子结点数Status DeleteBST(BSTree &amp;T,int key,bool &amp;taller);//删除结点Status Delete(BSTree &amp;p,bool &amp;taller);Status Delete2(BSTree &amp;p,bool taller,ElemType &amp;f);void MU(); //选择菜单//-------------------------------------//-------------------------------------初始化队列{Q.base=(QElemType*)malloc(MAXQSIZE*sizeof(QElemType)); if(!Q.base)return ERROR;Q.front=Q.rear=0;return OK;}//-------------------------------------进队列Status EnQueue(SqQueue &amp;Q,QElemType e){if((Q.rear+1)%MAXQSIZE==Q.front)return ERROR;Q.base[Q.rear]=e;Q.rear=(Q.rear+1)%MAXQSIZE;return OK;}//-------------------------------------出队列Status DeQueue(SqQueue &amp;Q,QElemType &amp;e){if(Q.front==Q.rear)return ERROR;e=Q.base[Q.front];Q.front=(Q.front+1)%MAXQSIZE;return OK;}//-------------------------------------获队列首Status GetHead(SqQueue Q,QElemType &amp;e){if(Q.front==Q.rear)return ERROR;e=Q.base[Q.front];return OK;}//-------------------------------------队列长度int QueueLength(SqQueue Q){return (Q.rear-Q.front+MAXQSIZE)%MAXQSIZE;}//-------------------------------------遍历队列{int i;i=Q.front;if(Q.front==Q.rear)printf(&quot;The Queue is Empty!&quot;);else{printf(&quot;The Queue is:&quot;);while(i!=Q.rear){printf(&quot;% d&quot;,Q.base[i]);i=i+1;}}printf(&quot;\n&quot;);return OK;}//-------------------------------------//-------------------------------------初始化栈Status InitStack(SqStack &amp;S){S.base=(SElemType*)malloc(STACK_INIT_SIZE*sizeof(SElemType));if(!S.base)return ERROR;S.top=S.base;S.stacksize=STACK_INIT_SIZE;return OK;}//-------------------------------------进栈Status Push(SqStack &amp;S,SElemType e){if(S.top-S.base&gt;=S.stacksize){S.base=(SElemType*)realloc(S.base,(S.stacksize+STACKINCREMENT)*sizeof(SElemType)); if(S.base)return ERROR;S.top=S.base+S.stacksize;S.stacksize+=STACKINCREMENT;}*S.top++=e;return OK;}//-------------------------------------出栈Status Pop(SqStack &amp;S,SElemType &amp;e){if(S.top==S.base)return ERROR;e=*--S.top;return OK;}//-------------------------------------获栈顶Status GetTop(SqStack S,SElemType &amp;e){if(S.top==S.base)return ERROR;e=*(S.top-1);return OK;}//-------------------------------------栈的长度int StackLength(SqStack S){int i=0;while(S.top!=S.base){i++;S.top--;}return i;}//-------------------------------------判栈空Status StackEmpty(SqStack S){if(S.top==S.base) return 1;else return 0;}//-------------------------------------栈的遍历Status StackTraverse(SqStack S){SElemType *p=(SElemType*)malloc(sizeof(SElemType)); p=S.top;if(S.top==S.base)printf(&quot;The Stack is Empty!&quot;);else{printf(&quot;The Stack is:&quot;);p--;S.base--;while(p!=S.base){printf(&quot;% d&quot;,*p);p--;}}printf(&quot;\n&quot;);return OK;}//-----------------------------------------------------------------//-----------------------------------------------------------------右旇void R_Rotate(BSTree &amp;p){BSTree lc;lc=p-&gt;lchild;p-&gt;lchild=lc-&gt;rchild;lc-&gt;rchild=p;p=lc;}//-----------------------------------------------------------------左旇void L_Rotate(BSTree &amp;p){BSTree rc;rc=p-&gt;rchild;p-&gt;rchild=rc-&gt;lchild;rc-&gt;lchild=p;p=rc;}//-----------------------------------------------------------------平衡二叉树结点插入Status InsertAVL(BSTree &amp;T,ElemType e,Boolean &amp;taller){if(!T){T=(BSTree)malloc(sizeof(BSTNode));T-&gt;data=e;T-&gt;lchild=T-&gt;rchild=NULL;T-&gt;bf=EH;taller=TRUE;}elseif(EQ(e,T-&gt;data)) {taller=FALSE;return 0;}//已经有结点了if(LT(e,T-&gt;data)){if(!InsertAVL(T-&gt;lchild,e,taller)) return 0;//左子树的深度增加if(taller)switch(T-&gt;bf){case LH:LeftBalance(T);taller=FALSE;break;case EH:T-&gt;bf=LH;taller=TRUE;break;case RH:T-&gt;bf=EH;taller=FALSE;break;}}else{if(!InsertAVL(T-&gt;rchild,e,taller)) return 0;//右子树的深度增加if(taller)switch(T-&gt;bf){case LH:T-&gt;bf=EH;taller=FALSE;break;case EH:T-&gt;bf=RH;taller=TRUE;break;case RH:RigthBalance(T);taller=FALSE;break;}}}return 1;//-----------------------------------------------------------------左平衡void LeftBalance(BSTree &amp;T){BSTree c,rd;c=T-&gt;lchild;switch(c-&gt;bf){case LH:T-&gt;bf=c-&gt;bf=EH;R_Rotate(T);break;case RH:rd=c-&gt;rchild;switch(rd-&gt;bf){case LH:T-&gt;bf=RH; c-&gt;bf=EH;break;case EH:T-&gt;bf=c-&gt;bf=EH; break;case RH:T-&gt;bf=EH;c-&gt;bf=LH;break;}rd-&gt;bf=EH;L_Rotate(T-&gt;lchild);R_Rotate(T);}}//-----------------------------------------------------------------右平衡void RigthBalance(BSTree &amp;T){BSTree rd,lc;rd=T-&gt;rchild;switch(rd-&gt;bf){case RH:T-&gt;bf=rd-&gt;bf=EH;L_Rotate(T);break;case LH:lc=rd-&gt;lchild;switch(lc-&gt;bf){case RH:T-&gt;bf=LH;rd-&gt;bf=EH;break;case EH:T-&gt;bf=rd-&gt;bf=EH;break;case LH:T-&gt;bf=EH;rd-&gt;bf=RH;break;}lc-&gt;bf=EH;R_Rotate(T-&gt;rchild);L_Rotate(T);}}//-----------------------------------------------------------------建树Status CreateBST(BSTree &amp;T,int n){T=NULL;bool taller=FALSE;int k,i;for(i=1;i&lt;=n;i++){scanf(&quot;%d&quot;,&amp;k);InsertAVL(T,k,taller);}return OK;}//-----------------------------------------------------------------访问Status Visit(ElemType e){printf(&quot;%d &quot;,e);return OK;}//-----------------------------------------------------------------前序遍历Status PreOrderTraverse(BSTree T){if(T){if(Visit(T-&gt;data))if(PreOrderTraverse(T-&gt;lchild))if(PreOrderTraverse(T-&gt;rchild))return OK;return ERROR;}elsereturn OK;}//-----------------------------------------------------------------前序非递归遍历Status preOrderIter(BSTree T){BSTree p,q;p=T;SqStack S;if (T == NULL) return ERROR;InitStack(S);Push(S,p);while (!StackEmpty(S)){GetTop(S,p);Visit(p-&gt;data);Pop(S,p);if (p-&gt;rchild != NULL)Push(S,p-&gt;rchild);if (p-&gt;lchild != NULL)Push(S,p-&gt;lchild);}printf(&quot;\n&quot;);return OK;}//-----------------------------------------------------------------中序遍历Status InOrderTraverse(BSTree T){if(T){if(InOrderTraverse(T-&gt;lchild))if(Visit(T-&gt;data))if(InOrderTraverse(T-&gt;rchild))return OK;return ERROR;}elsereturn OK;}//-----------------------------------------------------------------中序非递归遍历Status inOrderIter(BSTree T){BSTree p;p=T;SqStack S;if (T == NULL) return ERROR;InitStack(S);while (p!= NULL || !StackEmpty(S)){if (p!= NULL){Push(S,p);p=p-&gt;lchild;}else{GetTop(S,p);Visit(p-&gt;data);Pop(S,p);p=p-&gt;rchild;}}printf(&quot;\n&quot;);return OK;}//-----------------------------------------------------------------后序遍历Status PostOrderTraverse(BSTree T){if(T){if(PostOrderTraverse(T-&gt;lchild))if(PostOrderTraverse(T-&gt;rchild))if(Visit(T-&gt;data))return OK;return ERROR;}elsereturn OK;}//-----------------------------------------------------------------后序非递归遍历Status postOrderIter(BSTree T){if (!T) return 0;BSTree p,q;p=T;SqStack S1,S2;InitStack(S1);InitStack(S2);Push(S1,p);while (!StackEmpty(S1)){GetTop(S1,q);Push(S2,q);Pop(S1,p);if (q-&gt;lchild)Push(S1,q-&gt;lchild);if (q-&gt;rchild)Push(S1,q-&gt;rchild);}while (!StackEmpty(S2)){GetTop(S2,q);Visit(q-&gt;data);Pop(S2,q);}printf(&quot;\n&quot;);return OK;}//-----------------------------------------------------------------在二叉树中查找关键词Status FindBST(BSTree T,ElemType key,int &amp;n){if(!T) return ERROR;if(EQ(key,T-&gt;data)) {n=1;return OK;}else if(LT(key,T-&gt;data)){FindBST( T-&gt;lchild, key,n);}else FindBST( T-&gt;rchild,key,n);return OK;}//-----------------------------------------------------------------层次遍历Status OverTraverse(BSTree &amp;T){BSTree p;SqQueue Q;if(!InitQueue(Q)) return ERROR;p=T;if(!T) return ERROR;EnQueue(Q,p);while(QueueLength(Q)){DeQueue(Q,p);Visit(p-&gt;data);if(p-&gt;lchild) EnQueue(Q,p-&gt;lchild);if(p-&gt;rchild) EnQueue(Q,p-&gt;rchild);}return OK;}//-----------------------------------------------------------------交换左右子树Status OverChang(BSTree &amp;T){BSTree q;if(T){q=T-&gt;lchild;T-&gt;lchild=T-&gt;rchild;T-&gt;rchild=q;switch(T-&gt;bf){case LH:T-&gt;bf=RH;break;case EH:break;case RH:T-&gt;bf=LH;break;}if(OverChang(T-&gt;lchild))if(OverChang(T-&gt;rchild))return OK;return ERROR;}elsereturn OK;}//-----------------------------------------------------------------求树的深度int BSTDeep(BSTree T){int ln=0,rn=0,n=0;if(T){ln=(BSTDeep(T-&gt;lchild));rn=(BSTDeep(T-&gt;rchild));n=ln&gt;rn?ln:rn;n++;return n;}elsereturn 0;}//-----------------------------------------------------------------求叶子结点数Status Sum(BSTree T,int &amp;n){if(T){ if((T-&gt;lchild==NULL)&amp;&amp;(T-&gt;rchild==NULL)) n++;if(Sum(T-&gt;lchild,n))if(Sum(T-&gt;rchild,n))return OK;return ERROR;}elsereturn OK;}//-----------------------------------------------------------------删除结点Status DeleteBST(BSTree &amp;T,int key,bool &amp;taller) {if(!T) return FALSE;else{if(EQ(key,T-&gt;data)){Delete(T,taller);}else if(LT(key,T-&gt;data)){if(!DeleteBST(T-&gt;lchild,key,taller)) return 0;if(taller)switch(T-&gt;bf){case LH:T-&gt;bf=EH;taller=FALSE;break;case EH:T-&gt;bf=RH;taller=FALSE;break;case RH:RigthBalance(T);taller=FALSE;break;}}else{if(!DeleteBST(T-&gt;rchild,key,taller)) return 0;if(taller)switch(T-&gt;bf){case LH:LeftBalance(T);taller=TRUE;break;case EH:T-&gt;bf=LH;taller=FALSE;break;case RH:T-&gt;bf=EH;taller=FALSE;break;}}}return OK;}//----------------------------------------------------------------- Status Delete(BSTree &amp;p,bool &amp;taller){BSTree q,s;ElemType f;if(!p-&gt;rchild){q=p;p=p-&gt;lchild;taller=true;free(q);}else if(!p-&gt;lchild){q=p;p=p-&gt;rchild;taller=true;free(q);}else{q=p;s=p-&gt;lchild;if(!s-&gt;rchild){p-&gt;lchild=s-&gt;lchild;free(s);taller=TRUE;}else{Delete2(p,taller,f);p-&gt;data=f;}}return OK;}//----------------------------------------------------------------- Status Delete2(BSTree &amp;p,bool taller,ElemType &amp;f) {BSTree q;q=p-&gt;rchild;if(q-&gt;rchild){if(!Delete2(p-&gt;rchild,taller,f)) return 0;if(taller)switch(p-&gt;bf){case LH:LeftBalance(p);taller=TRUE;break;case EH:p-&gt;bf=LH;taller=FALSE;break;case RH:p-&gt;bf=EH;taller=FALSE;break;}}else{p-&gt;rchild=q-&gt;lchild;f=q-&gt;data;taller=TRUE;free(q);}return OK;}//-----------------------------------------------------------------选择菜单void MU(){printf(&quot;===================================================\n&quot;); printf(&quot;1 建一棵新的二叉树\n&quot;);printf(&quot;2 插入新的结点\n&quot;);printf(&quot;3 前,中,后序遍历二叉树\n&quot;);printf(&quot;4 前序、中序、后序遍历的非递归算法\n&quot;);printf(&quot;5 层次遍历二叉树\n&quot;);printf(&quot;6 在二叉树中查找给定关键字(函数返回值为成功1,失败0)\n&quot;); printf(&quot;7 交换各结点的左右子树\n&quot;);printf(&quot;8 求二叉树的深度\n&quot;);printf(&quot;9 叶子结点数\n&quot;);printf(&quot;10 删除某结点\n&quot;);printf(&quot;===================================================\n&quot;); printf(&quot;请选择:&quot;);}//-----------------------------------------------------------------主函数int main(){BSTree T=NULL;bool taller=FALSE;int n,k,i;while(true){MU();scanf(&quot;%d&quot;,&amp;n);switch(n){case 1:scanf(&quot;%d&quot;,&amp;k);if(CreateBST(T,k)) printf(&quot;建树成功!\n&quot;);else printf(&quot;建树失败!\n&quot;);break;case 2:printf(&quot;请输入要插入的数字:&quot;);scanf(&quot;%d&quot;,&amp;k);if(InsertAVL(T,k,taller)) printf(&quot;%d 插入成功!\n&quot;,k); else printf(&quot;二叉树中已经存在%d\n&quot;,k); break;case 3:PreOrderTraverse( T); printf(&quot;\n&quot;); InOrderTraverse( T); printf(&quot;\n&quot;); PostOrderTraverse( T); printf(&quot;\n&quot;);break;case 4:preOrderIter( T);inOrderIter( T);postOrderIter( T);break;case 5:OverTraverse(T);printf(&quot;\n&quot;);break;case 6:scanf(&quot;%d&quot;,&amp;k);i=0;FindBST( T, k,i);printf(&quot;%d\n&quot;,i);break;case 7:if(OverChang(T)) printf(&quot;操作成功!\n&quot;);else printf(&quot;操作失败!\n&quot;);break;case 8:k=BSTDeep( T);printf(&quot;二叉树的深度是%d!\n&quot;, k);break;case 9:k=0;Sum( T,k);printf(&quot;叶子的结点数为%d\n&quot;,k);break;case 10:scanf(&quot;%d&quot;,&amp;k);if(DeleteBST(T, k,taller)) printf(&quot;操作成功!\n&quot;); else printf(&quot;二叉树中不存在%d!\n&quot;,k); break;default:printf(&quot;输入不正确,请重新输入!\n&quot;);}}return 0;}。

相关文档
最新文档