平衡二叉树(AVL)的查找、插入和删除

合集下载

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

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

平衡二叉树操作的演示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);}。

平衡二叉树和二叉排序树(二叉搜索树)区别

平衡二叉树和二叉排序树(二叉搜索树)区别

平衡⼆叉树和⼆叉排序树(⼆叉搜索树)区别
平衡⼆叉树是⼀种⼆叉搜索树。

其可以保证在log2(n)的时间内找到节点,⽽普通的⼆叉搜索树在最坏情况下性能近似与链
表,所⽤时间为log(n)。

常⽤的平衡⼆叉树有AVL树和红⿊树其算法的难点在于插⼊删除节点后树的旋转
平衡⼆叉树 ----> O(log2(n))
普通⼆叉搜索树 ----> O(n)
在⼆叉搜索树的插⼊和删除运算中,采⽤平衡树的优点是:使树的结构较好,从⽽提⾼查找运算的速度。

缺点是:是插⼊和删除运算变得复杂化,从⽽降低了他们的运算速度。

对⼆叉搜索树删除节点⽽引起的不平衡性进⾏的操作⽐插⼊节点的情况要复杂,在此就不再论述了。

操作系统的设计也有⽤到哦
很多数据库的实现是基于更复杂的平衡⼆叉树
可以⾃⼰实现⼀个集合或者map,统计单词出现的次数
stl的map/set都在⽤
普通⼆叉搜索树最坏情况是只有左边⼀个分⽀,如1-2-3-4-5(5在最上⾯,1在左下⾓),但是平衡⼆叉树可以调整。

为1-2-3-4-5(3在最上⾯,1在左下⾓,5在右下⾓)。

平衡⼆叉树 ----> O(log2(n))
普通⼆叉搜索树 ----> O(n)
所以平衡⼆叉树的搜索性能⽐⼆叉搜索树(⼆叉排序树)好。

搜索树的基本操作方法

搜索树的基本操作方法

搜索树的基本操作方法
搜索树是一种有序的二叉树数据结构,常用于存储和搜索数据。

基本的操作方法包括插入、删除和查找。

1. 插入操作(insert):向搜索树中插入新节点。

从根节点开始遍历搜索树,如果待插入节点值小于当前节点值,则继续向左子树搜索;如果待插入节点值大于当前节点值,则继续向右子树搜索;直到找到一个空位置,将待插入节点插入到该位置。

2. 删除操作(delete):删除指定节点。

先在搜索树中找到待删除节点,根据不同情况进行处理:
a) 如果待删除节点没有子节点,直接删除它。

b) 如果待删除节点只有一个子节点,将子节点替代待删除节点的位置。

c) 如果待删除节点有两个子节点,则寻找待删除节点的前驱节点或后继节点来替代该节点。

前驱节点是指比待删除节点值小的最大节点,后继节点是指比待删除节点值大的最小节点。

可以选择使用前驱节点或后继节点来替代待删除节点。

3. 查找操作(search):在搜索树中查找指定值的节点。

从根节点开始遍历搜索树,如果要查找的值等于当前节点值,则返回该节点;如果要查找的值小于当前节点值,则继续向左子树搜索;如果要查找的值大于当前节点值,则继续向右子树搜索。

如果找到了匹配节点,则返回节点;如果搜索到空节点(未找到匹配节点),则返回空值。

以上是搜索树的基本操作方法,对于不同的搜索树实现,可能会有一些其他特定的操作方法。

二叉树的基本操作

二叉树的基本操作

二叉树的基本操作二叉树是一种常见的数据结构,它由节点组成,每个节点最多有两个子节点。

二叉树在计算机领域中得到广泛应用,它的基本操作包括插入、删除、查找、遍历等。

1.插入操作:二叉树的插入操作是将一个新的节点添加到已有的二叉树中的过程。

插入操作会按照一定规则将新节点放置在正确的位置上。

插入操作的具体步骤如下:-首先,从根节点开始,比较新节点的值与当前节点的值的大小关系。

-如果新节点的值小于当前节点的值,则将新节点插入到当前节点的左子树中。

-如果新节点的值大于当前节点的值,则将新节点插入到当前节点的右子树中。

-如果当前节点的左子树或右子树为空,则直接将新节点插入到该位置上。

-如果当前节点的左子树和右子树都不为空,则递归地对左子树或右子树进行插入操作。

2.删除操作:二叉树的删除操作是将指定节点从二叉树中删除的过程。

删除操作有以下几种情况需要考虑:-如果待删除节点是叶子节点,则直接将其从二叉树中删除即可。

-如果待删除节点只有一个子节点,则将其子节点替换为待删除节点的位置即可。

-如果待删除节点有两个子节点,则需要找到其左子树或右子树中的最大节点或最小节点,将其值替换为待删除节点的值,然后再删除最大节点或最小节点。

3.查找操作:二叉树的查找操作是在二叉树中查找指定值的节点的过程。

查找操作的具体步骤如下:-从根节点开始,将待查找值与当前节点的值进行比较。

-如果待查找值等于当前节点的值,则返回该节点。

-如果待查找值小于当前节点的值,则在当前节点的左子树中继续查找。

-如果待查找值大于当前节点的值,则在当前节点的右子树中继续查找。

-如果左子树或右子树为空,则说明在二叉树中找不到该值。

4.遍历操作:二叉树的遍历操作是按照一定规则依次访问二叉树中的每个节点。

有三种常用的遍历方式:- 前序遍历(Preorder Traversal):先访问根节点,然后递归地前序遍历左子树和右子树。

- 中序遍历(Inorder Traversal):先递归地中序遍历左子树,然后访问根节点,最后递归地中序遍历右子树。

平衡二叉树10.3.2

平衡二叉树10.3.2

11
28
96 98
25
(1) LL型调整 型调整 p A 1 2
调整方法: 调整方法: 单向右旋平衡,即将 的左孩子 单向右旋平衡,即将A的左孩子 B 向右上旋转代替 成为根结点, 向右上旋转代替A成为根结点 成为根结点, 结点向右下旋转成为B的右 将A结点向右下旋转成为 的右 结点向右下旋转成为 子树的根结点, 子树的根结点,而B的原右子树 的原右子树 则作为A结点的左子树 结点的左子树. 则作为 结点的左子树. h d e B
1 38 -1 24 88
0 -1 -2
0
11
28 1
96
0
-1 0
25
0
98
1,平衡二叉树插入结点的调整方法
若向平衡二叉树中插入一个新结点后破坏了平衡二叉树的平衡性, 若向平衡二叉树中插入一个新结点后破坏了平衡二叉树的平衡性, 首先从根结点到该新插入结点的路径之逆向根结点方向找第一个失去平 衡的结点, 衡的结点,然后以该失衡结点和它相邻的刚查找过的两个结点构成调整 子树(最小不平衡子树 即调整子树是指以离插入结点最近,且平衡因子 最小不平衡子树), 子树 最小不平衡子树 ,即调整子树是指以离插入结点最近 且平衡因子 绝对值大于1的结点为根结点的子树 使之成为新的平衡子树. 的结点为根结点的子树,使之成为新的平衡子树 绝对值大于 的结点为根结点的子树 使之成为新的平衡子树. 38 24 88 -2
(2)RR型调整 型调整 p A -1 -2
调整方法: 调整方法: 单向左旋平衡:即将 的右孩子 的右孩子B向 单向左旋平衡:即将A的右孩子 向 左上旋转代替A成为根结点 成为根结点, 左上旋转代替 成为根结点,将A结 结 点向左下旋转成为B的左子树的根 点向左下旋转成为 的左子树的根 结点, 的原左子树则作为A结点 结点,而B的原左子树则作为 结点 的原左子树则作为 的右子树. 的右子树. B

AVL树和红黑树的性能对比和适用场景

AVL树和红黑树的性能对比和适用场景

AVL树和红黑树的性能对比和适用场景AVL树和红黑树都是常用的自平衡二叉查找树,它们在不同的应用场景下具有不同的性能特点。

本文将对AVL树和红黑树的性能进行对比,并分析它们适用的场景。

一、性能对比1. 插入和删除操作AVL树和红黑树在插入和删除操作方面具有不同的性能表现。

由于AVL树要求保持平衡,每次插入或删除操作后都需要进行旋转操作来调整树的平衡。

这样虽然能够保持树的平衡,但是会造成频繁的旋转操作,导致性能较低。

而红黑树则通过颜色标记和旋转操作来保持树的平衡,相比AVL树的旋转操作更少,因此在插入和删除操作方面性能更优。

2. 查找操作在查找操作方面,AVL树和红黑树的性能相当。

它们都保持了二叉查找树的性质,可以在对数时间内完成查找操作。

3. 内存占用由于AVL树要存储额外的平衡信息,每个节点需要额外的一个整数来表示平衡因子,因此相比红黑树来说,AVL树的内存占用更高。

二、适用场景1. 数据插入与删除频繁的场景如果应用场景中涉及频繁的数据插入和删除操作,而对查找操作的性能要求相对较低,则适合选择红黑树。

红黑树通过更少的旋转操作来保持树的平衡,能够在频繁插入和删除操作时,保持较好的性能。

2. 数据查询频繁的场景如果应用场景中涉及频繁的数据查询操作,而对插入和删除操作的性能要求相对较低,则适合选择AVL树。

AVL树由于保持了严格的平衡性,能够在频繁查询操作时,提供更高的查找性能。

3. 对内存占用有限制的场景如果应用场景对内存占用有较严格的限制,则适合选择红黑树。

红黑树相比AVL树的内存占用更低,能够在有限的内存条件下,存储更多的节点。

4. 平衡性要求高且内存占用不是关键问题的场景如果应用场景对平衡性要求较高,而对内存占用没有过多的限制,则AVL树是更好的选择。

AVL树能够保持严格的平衡性,但相对红黑树来说,需要更多的旋转操作,导致性能较低。

三、总结AVL树和红黑树是常用的自平衡二叉查找树,在不同的应用场景下具有不同的性能表现。

平衡二叉树

平衡二叉树
2算法
编辑
红黑树
红黑树是一种自平衡二叉查找树,是在计算机科学中用到的一种数据结构,典型的用途是实现关联数组。它是在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操作。

AVL树及其平衡性

AVL树及其平衡性

AVL树及其平衡性AVL树是一种自平衡的二叉搜索树,它得名于它的发明者Adelson-Velsky和Landis。

AVL树在插入和删除节点时会通过旋转操作来保持树的平衡,以确保树的高度始终保持在一个较小的范围内,从而提高搜索、插入和删除操作的效率。

本文将介绍AVL树的基本概念、特点以及如何保持其平衡性。

一、AVL树的基本概念AVL树是一种二叉搜索树,具有以下特点:1. 每个节点最多有两个子节点,左子节点的值小于父节点的值,右子节点的值大于父节点的值;2. 每个节点都有一个平衡因子(Balance Factor),定义为左子树的高度减去右子树的高度;3. AVL树的平衡因子必须为-1、0或1,即任意节点的左右子树高度差不超过1;4. AVL树中任意节点的左子树和右子树都是AVL树。

二、AVL树的平衡性AVL树通过旋转操作来保持树的平衡,主要包括左旋转、右旋转、左右旋转和右左旋转四种操作。

在插入或删除节点后,如果AVL树的平衡因子不满足要求,就需要进行相应的旋转操作来调整树的结构,以保持平衡性。

1. 左旋转(LL旋转)当某个节点的平衡因子为2,且其左子树的平衡因子为1或0时,需要进行左旋转操作。

左旋转是将当前节点向左旋转,使其右子节点成为新的根节点,原根节点成为新根节点的左子节点,新根节点的左子节点成为原根节点的右子节点。

2. 右旋转(RR旋转)当某个节点的平衡因子为-2,且其右子树的平衡因子为-1或0时,需要进行右旋转操作。

右旋转是将当前节点向右旋转,使其左子节点成为新的根节点,原根节点成为新根节点的右子节点,新根节点的右子节点成为原根节点的左子节点。

3. 左右旋转(LR旋转)当某个节点的平衡因子为2,且其左子树的平衡因子为-1时,需要进行左右旋转操作。

左右旋转是先对当前节点的左子节点进行右旋转,然后再对当前节点进行左旋转。

4. 右左旋转(RL旋转)当某个节点的平衡因子为-2,且其右子树的平衡因子为1时,需要进行右左旋转操作。

C平衡二叉树(AVL)创建和删除

C平衡二叉树(AVL)创建和删除

C平衡⼆叉树(AVL)创建和删除 AVL是最先发明的⾃平衡⼆叉查找树算法。

在AVL中任何节点的两个⼉⼦⼦树的⾼度最⼤差别为⼀,所以它也被称为⾼度平衡树,n个结点的AVL树最⼤深度约1.44log2n。

查找、插⼊和删除在平均和最坏情况下都是O(log n)。

增加和删除可能需要通过⼀次或多次树旋转来重新平衡这个树。

定义 ⽤LH,EH,RH分别表⽰左⼦树⾼,等⾼,右⼦树⾼,即平衡因⼦1、0、-1#include <stdio.h>#include <stdlib.h>#include <stdbool.h>#define LH 1 // 左⾼#define EH 0 // 等⾼#define RH -1 // 右⾼typedef struct TreeNode{int data;int bf;struct TreeNode *left, *right;}TreeNode; 旋转处理 左旋和右旋,记住“左逆右顺”就可以/************************************************* 对以*p为根的⼆叉排序树作右旋处理,处理之后p指向新的树根结点,* A B* / / \* B 旋转后变为 C A* / \ /* C D D* 即旋转处理之前的左⼦树的结点。

************************************************/void r_rotate(TreeNode **p){TreeNode *l = (*p)->left;(*p)->left = l->right;l->right = (*p);*p = l;}/************************************************* 对以*p为根的⼆叉排序树作左旋处理,处理之后p指向新的树根结点,* A B* \ / \* B 旋转后变为 A D* / \ \* C D C* 即旋转处理之前的右⼦树的结点。

名词解释平衡二叉树

名词解释平衡二叉树

平衡二叉树介绍平衡二叉树(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. 任意节点到其每个叶子节点的路径上包含相同数目的黑色节点。

通过对节点进行颜色变换和旋转操作,红黑树可以在插入和删除节点的过程中保持平衡。

平衡二叉树的应用平衡二叉树在计算机科学中有广泛的应用。

AVL树数据结构的特点与使用场景

AVL树数据结构的特点与使用场景

AVL树数据结构的特点与使用场景AVL树是一种自平衡的二叉搜索树,它在插入或删除节点时会通过旋转操作来保持树的平衡,以确保树的高度始终保持在较小的范围内。

AVL树得名于其发明者Adelson-Velsky和Landis,是一种高度平衡的二叉搜索树,具有快速的查找、插入和删除操作的特点。

在本文中,将介绍AVL树数据结构的特点以及其在实际应用中的使用场景。

一、AVL树的特点1. 自平衡性:AVL树是一种自平衡的二叉搜索树,任何时刻,AVL 树的任意节点的左右子树的高度差不超过1。

当插入或删除节点后,AVL树会通过旋转操作来保持树的平衡,以确保树的高度始终保持在较小的范围内,从而保证了查找、插入和删除操作的时间复杂度为O(log n)。

2. 高度平衡:由于AVL树的自平衡性,使得树的高度相对较低,这样在进行查找操作时,平均查找时间较短,提高了搜索效率。

3. 严格平衡:AVL树是一种严格平衡的二叉搜索树,任何时刻,AVL树的任意节点的左右子树的高度差不超过1,这种严格平衡性保证了AVL树的高度始终保持在较小的范围内,使得其在各种操作下都能保持高效性。

4. 插入和删除操作复杂度低:由于AVL树的自平衡性,插入和删除节点时需要进行旋转操作来保持树的平衡,但这些旋转操作的时间复杂度为O(log n),因此插入和删除操作的复杂度仍然为O(log n),保证了操作的高效性。

二、AVL树的使用场景1. 数据库索引:在数据库系统中,AVL树常被用作索引结构,用于加速数据库的查找操作。

由于AVL树具有快速的查找、插入和删除操作,能够保持树的平衡,因此在数据库索引中得到广泛应用。

2. 编辑器中的自动补全功能:在文本编辑器或代码编辑器中,常常需要实现自动补全功能,AVL树可以用来存储单词或代码片段,通过快速查找实现自动补全功能,提高编辑效率。

3. 路由表:在网络路由中,需要快速查找目标地址对应的路由信息,AVL树可以用来存储路由表,通过快速查找实现高效的路由转发,提高网络传输效率。

二叉树实验知识点总结

二叉树实验知识点总结

二叉树实验知识点总结
一、二叉树的基本概念
二叉树是一种特殊的树形结构,其每个节点最多只有两个子节点。

二叉树分为满二叉树、完全二叉树和普通二叉树等类型。

二、遍历方式
1.前序遍历:先访问当前节点,再遍历左子树和右子树;
2.中序遍历:先遍历左子树,再访问当前节点,最后遍历右子树;
3.后序遍历:先遍历左子树和右子树,最后访问当前节点;
4.层次遍历:按照从上到下、从左到右的顺序依次访问每个节点。

三、常见操作
1.插入节点:在二叉搜索树中插入一个新的节点;
2.删除节点:在二叉搜索树中删除一个指定的节点;
3.查找节点:在二叉搜索树中查找一个指定的节点;
4.求深度:计算二叉搜索树的深度。

四、平衡二叉树
平衡二叉树是一种特殊的二叉搜索树,其左右子树高度差不能超过1。

常见的平衡二叉搜索包括红黑树、AVL 树等。

五、应用场景
1.数据库索引;
2.哈夫曼编码;
3.表达式求值;
4.图形处理等。

六、注意事项
1.二叉树的插入、删除和查找操作需要保证二叉树的结构不被破坏;
2.平衡二叉树的实现需要注意平衡因子的计算和旋转操作的实现;
3.在使用二叉树进行算法设计时,需要考虑遍历方式和时间复杂度等问题。

七、总结
二叉树是一种重要的数据结构,在算法设计中有广泛的应用。

掌握二叉树的基本概念、遍历方式、常见操作和应用场景,可以帮助我们更好地理解和使用这种数据结构。

同时,我们需要注意在实际应用中遵循相关规范,保证程序的正确性和效率。

原题目:比较二叉树和AVL树的区别。

原题目:比较二叉树和AVL树的区别。

原题目:比较二叉树和AVL树的区别。

原题目:比较二叉树和AVL树的区别
二叉树和AVL树是常用的数据结构,它们都是树形结构,但
在某些方面有一些区别。

1. 定义:
- 二叉树:每个节点最多有两个子节点的树结构。

- AVL树:也是一种二叉搜索树,但它具有自平衡特性。

2. 平衡特性:
- 二叉树:二叉树没有保持平衡的要求,所以可能出现不平衡
的情况。

- AVL树:AVL树要求在插入或删除节点后,保持树的平衡状态。

每个节点的左右子树高度差(平衡因子)不超过1。

3. 插入和删除操作的效率:
- 二叉树:在二叉树中插入和删除节点的效率取决于树的形状,可能较低。

- AVL树:由于AVL树要保持平衡,插入和删除节点时需要通过旋转操作来调整树的结构,因此插入和删除的效率可能较低。

4. 查找操作的效率:
- 二叉树:二叉树的查找操作时间复杂度为O(log n),其中n为节点数量。

- AVL树:由于AVL树的平衡特性,它的查找操作时间复杂度也为O(log n)。

5. 空间占用:
- 二叉树:二叉树的空间占用取决于树的形状,没有特定的要求。

- AVL树:由于AVL树需要维护平衡,它可能需要更多的额外空间。

总结:二叉树和AVL树都是树形结构,但AVL树具有自平衡特性。

相比之下,二叉树没有要求保持平衡,所以插入和删除的效率可能较低。

同时,AVL树的插入和删除操作需要通过旋转来实现平衡,因此它的效率可能较低。

但二叉树和AVL树的查找操作时间复杂度都为O(log n),并且都可以用于不同的应用场景。

avl方案介绍

avl方案介绍

avl方案1. 引言AVL树是一种自平衡二叉查找树,它在操作过程中保持树的高度平衡,从而保证了各种基本操作的时间复杂度为O(log n)。

本文将介绍AVL树的原理、实现方法以及应用场景。

2. AVL树的原理AVL树是由G.M. Adelson-Velsky和E.M. Landis在1962年提出的,它的名称取自于他们的名字的首字母。

AVL树的特点是每个节点的左子树和右子树的高度差不超过1,即保证了树的高度平衡。

AVL树的插入和删除操作会导致树的失衡,为了维持树的平衡,AVL树使用了旋转操作。

旋转操作主要包括左旋和右旋,通过重新调整子树的结构来使得树重新达到平衡。

3. 实现AVL树实现AVL树可以采用递归或迭代的方式,这里以递归方式为例进行说明。

3.1 AVL树节点定义首先需要定义AVL树的节点结构,一个简单的AVL树节点可以包括以下几个字段:class AVLNode:def__init__(self, key):self.key = keyself.left =Noneself.right =Noneself.height =1其中,key字段用于存储节点的键值,left和right字段分别指向节点的左子树和右子树,height字段表示节点的高度。

3.2 AVL树的插入操作AVL树的插入操作分为以下几个步骤:1.找到插入位置,若树为空,则直接插入新节点。

2.根据插入节点的键值与当前节点的键值进行比较,决定向左子树或右子树递归插入。

行旋转操作。

4.若当前节点失衡,根据失衡情况选择合适的旋转操作进行平衡调整。

下面是插入操作的递归实现代码:def insert(root, key):if not root:return AVLNode(key)elif key < root.key:root.left = insert(root.left, key)else:root.right = insert(root.right, key)root.height =1+ max(get_height(root.left), get_height(root.right)) balance = get_balance(root)# 左旋if balance >1and key < root.left.key:return rotate_right(root)# 右旋if balance <-1and key > root.right.key:return rotate_left(root)# 左右旋if balance >1and key > root.left.key:root.left = rotate_left(root.left)return rotate_right(root)# 右左旋if balance <-1and key < root.right.key:root.right = rotate_right(root.right)return rotate_left(root)return root3.3 AVL树的删除操作AVL树的删除操作也需要进行树的平衡调整,它分为以下几个步骤:1.找到待删除的节点。

课题_一步一步写平衡二叉树(AVL树)

课题_一步一步写平衡二叉树(AVL树)

一步一步写平衡二叉树(AVL树)平衡二叉树(Balanced Binary Tree)是二叉查找树的一个进化体,也是第一个引入平衡概念的二叉树。

1962年,G.M. Adelson-Velsky 和 E.M. Landis发明了这棵树,所以它又叫AVL树。

平衡二叉树要求对于每一个节点来说,它的左右子树的高度之差不能超过1,如果插入或者删除一个节点使得高度之差大于1,就要进行节点之间的旋转,将二叉树重新维持在一个平衡状态。

这个方案很好的解决了二叉查找树退化成链表的问题,把插入、查找、删除的时间复杂度最好情况和最坏情况都维持在O(logN)。

但是频繁旋转会使插入和删除牺牲掉O(logN)左右的时间,不过相对二叉查找树来说,时间上稳定了很多。

平衡二叉树实现的大部分过程和二叉查找树是一样的(学平衡二叉树之前一定要会二叉查找树),区别就在于插入和删除之后要写一个旋转算法去维持平衡,维持平衡需要借助一个节点高度的属性。

我参考了机械工业出版社的《数据结构与算法分析- C语言描述》写了一个C++版的代码。

这本书的AVLTree讲的很好,不过没有很完整的去描述。

我会一步一步的讲解如何写平衡二叉树,重点是平衡二叉树的核心部分,也就是旋转算法。

第一步:节点信息相对于二叉查找树的节点来说,我们需要用一个属性表示二叉树的高度,目的是维护插入和删除过程中的旋转算法。

代码如下://AVL树节点信息template<class T>class TreeNode{public:TreeNode():lson(NULL),rson(NULL),freq(1),hgt(0){}T data;//值int hgt;//以此节点为根的树的高度unsigned int freq;//频率TreeNode* lson;//指向左儿子的地址TreeNode* rson;//指向右儿子的地址};第二步:平衡二叉树(AVL)类的声明声明中的旋转函数将在后边的步骤中详解。

二叉树平衡因子

二叉树平衡因子

二叉树平衡因子
二叉树平衡因子(Balance Factor)是指在一棵二叉树中,某个节点
的左子树深度和右子树深度的差值。

平衡因子的范围可以是-1、0、1,如果范围超出了此范围,就需要进行旋转操作,使得此节点重新平衡。

在二叉树中,如果一些树高很高,一些树高很低,就会存在“垃圾桶
效应”,即计算时间复杂度的时候,树高较高的节点会浪费大量时间。

为了避免这种情况,需要让整棵树保持平衡,这就是平衡二叉树的原理。

平衡二叉树的根节点的平衡因子范围应该是 -1、0、1。

平衡二叉树常见的几种类型包括AVL树、红黑树和B-树。

其中,AVL 树和红黑树十分常用。

AVL树是一种早期出现的平衡二叉树,每个节
点的平衡因子范围都是-1、0或1,但因为旋转操作过于频繁,导致插入、删除节点效率低。

相反,红黑树虽然平衡因子范围不是很好,但
它通过它自己的特性保持了节点的平衡,增加、删除节点的效率高,
但相对于AVL树来说,层数会高一些。

B-树通常被用来处理需要大量数据存储和读取的应用场景。

例如,数
据库中的索引和存储。

总之,二叉树平衡因子是保证二叉树平衡的重要概念。

各种平衡二叉树的实现方式和应用场景略有不同,程序员在选择使用哪种平衡二叉树时,需要考虑自己的实际应用场景和需要。

二叉树的各种算法

二叉树的各种算法

二叉树的各种算法1.二叉树的前序遍历算法:前序遍历是指先访问根节点,再访问左子树,最后访问右子树的遍历顺序。

具体算法如下:-如果二叉树为空,则直接返回。

-访问根节点,并输出或进行其他操作。

-递归地前序遍历左子树。

-递归地前序遍历右子树。

2.二叉树的中序遍历算法:中序遍历是指先访问左子树,再访问根节点,最后访问右子树的遍历顺序。

具体算法如下:-如果二叉树为空,则直接返回。

-递归地中序遍历左子树。

-访问根节点,并输出或进行其他操作。

-递归地中序遍历右子树。

3.二叉树的后序遍历算法:后序遍历是指先访问左子树,再访问右子树,最后访问根节点的遍历顺序。

具体算法如下:-如果二叉树为空,则直接返回。

-递归地后序遍历左子树。

-递归地后序遍历右子树。

-访问根节点,并输出或进行其他操作。

4.二叉树的层序遍历算法:层序遍历是按照从上到下、从左到右的顺序逐层遍历二叉树的节点。

具体算法如下:-如果二叉树为空,则直接返回。

-创建一个队列,将根节点入队。

-循环执行以下步骤,直到队列为空:-出队并访问当前节点,并输出或进行其他操作。

-若当前节点的左子节点不为空,则将左子节点入队。

-若当前节点的右子节点不为空,则将右子节点入队。

5.二叉树的深度算法:二叉树的深度是指从根节点到叶节点的最长路径的节点数。

具体算法如下:-如果二叉树为空,则深度为0。

-否则,递归地计算左子树的深度和右子树的深度,然后取较大的值加上根节点的深度作为二叉树的深度。

6.二叉树的查找算法:二叉树的查找可以使用前序、中序或后序遍历来完成。

具体算法如下:-如果二叉树为空,则返回空。

-如果当前节点的值等于目标值,则返回当前节点。

-否则,先在左子树中递归查找,如果找到则返回找到的节点。

-如果左子树中未找到,则在右子树中递归查找,如果找到则返回找到的节点。

-如果左右子树中都未找到,则返回空。

7.二叉树的插入算法:二叉树的插入可以使用递归或循环来实现。

具体算法如下:-如果二叉树为空,则创建一个新节点作为根节点,并返回根节点。

平衡二叉树算法

平衡二叉树算法

平衡二叉树算法
平衡二叉树是一种特殊的二叉搜索树(BST),它通过限制每个节点的左右子树高度差不超过1来确保查找、插入和删除等操作具有良好的性能,时间复杂度接近O(log n)。

以下简要介绍其主要算法:
1. 构造:
- 初始化时可能为空树。

- 插入新节点时,需保持平衡性,若插入后破坏了平衡条件(即任意节点的左子树和右子树的高度差大于1),则需要进行旋转操作重新平衡树。

2. 旋转操作:
- 单旋转:包括左旋(LL旋转)和右旋(RR旋转),用于解决单边过高问题。

- LL旋转:当某个节点的左孩子与其左孩子的右孩子相比过高时进行。

- RR旋转:当某个节点的右孩子与其右孩子的左孩子相比过高时进行。

- 双旋转:包括LR旋转(先左旋后右旋)和RL旋转(先右旋后左旋),用于解决两边交替过高的情况。

3. 插入和删除后的调整:
- 在插入或删除节点导致树失去平衡时,从受影响节点向上回溯至根节点,沿途检查并更新节点的平衡因子,并在必要时执行相应的旋转操作以恢复平衡。

4. AVL树:
- 最早提出且广泛应用的平衡二叉搜索树类型是AVL树,它严格要求所有节点的平衡因子绝对值不大于1。

5. 其他实现:
- 红黑树也是一种平衡二叉搜索树,它的平衡条件相对宽松,允许任何路径的最大黑色高度相同,通过颜色标记和旋转/变色操作维护平衡。

总结来说,平衡二叉树算法的核心在于如何在保证二叉搜索树性质的基础上,通过特定规则的旋转操作实时维护树的平衡状态,从而保证高效的查询和修改性能。

二叉排序树与平衡二叉排序树基本操作的实现 文本文档

二叉排序树与平衡二叉排序树基本操作的实现 文本文档

10 设计说明书(论文)质量 30 综述简练完整,有见解;立论正确,论述充分,结论严谨合理;实验正确,分析处理科学。
11 创新 10 对前人工作有改进或突破,或有独特见解。
成绩
指导教师评语
指导教师签名: 年 月 日
摘要及关键字
本程序中的数据采用“树形结构”作为其数据结构。具体采用的是“二叉排序树”。
1.2.5 平衡二叉树( AVL树 )
①平衡二叉树(Balanced Binary Tree)是指树中任一结点的左右子树的高度大致相同。 ②任一结点的左右子树的高度均相同(如满二叉树),则二叉树是完全平衡的。通常,只要二叉树的高度为O(1gn),就可看作是平衡的。 ③平衡的二叉排序树指满足BST性质的平衡二叉树。 ④AVL树中任一结点的左、右子树的高度之差的绝对值不超过1。在最坏情况下,n个结点的AVL树的高度约为1.44lgn。而完全平衡的二叉树高度约为lgn,AVL树是最接近最优的。
1.2.4平均查找长度…………………………………………………………… 6
1.2.5平均二叉树(AVL树)…………………………………………………… 6
1.2.6平衡因子………………………………………………………………… 7
1.2.7平衡二叉树的调整方法…………………………………………………… 7
攀枝花学院本科学生课程设计任务书
题 目 二叉排序树与平衡二叉树的实现
1、课程设计的目的
使学生进一步理解和掌握课堂上所学各种基本抽象数据类型的逻辑结构、存储结构和操作实现算法,以及它们在程序中的使用方法。
使学生掌握软件设计的基本内容和设计方法,并培养学生进行规范化软件设计的能力。
3) 使学生掌握使用各种计算机资料和有关参考资料,提高学生进行程序设计的基本能力。

平衡二叉树构造方法

平衡二叉树构造方法

平衡二叉树构造方法构造平衡二叉树的方法有很多,其中一种绝妙的方法是通过AVL树进行构造。

AVL树是一种平衡二叉树,它的左子树和右子树的高度差不超过1、利用这种特性,我们可以通过以下步骤构造平衡二叉树:1.将需要构造平衡二叉树的数据按照升序或者降序排列。

2.选择数据的中间元素作为根节点。

3.将数据分成左右两个部分,分别作为根节点的左子树和右子树的数据。

4.递归地对左子树和右子树进行构造。

下面我们通过一个例子来具体说明这个方法:假设我们需要构造一个平衡二叉树,并且数据为1,2,3,4,5,6,7,8,9首先,我们将数据按照升序排列得到1,2,3,4,5,6,7,8,9、选择中间的元素5作为根节点。

然后,我们将数据分成两部分:1,2,3,4和6,7,8,9、递归地对这两个部分进行构造。

对于左子树,我们选择中间元素2作为根节点,将数据分成两部分:1和3,4、递归地构造这两个部分。

对于右子树,我们选择中间元素8作为根节点,将数据分成两部分:6,7和9、递归地构造这两个部分。

重复这个过程,直到所有的数据都被构造为节点。

最后得到的树就是一个平衡二叉树。

这个构造方法的时间复杂度是O(nlogn),其中n是数据的数量。

虽然它的时间复杂度比较高,但是它保证了构造的树是一个平衡二叉树,从而提高了数据的查找、插入和删除等操作的效率。

总结起来,通过AVL树进行构造是一种有效的方法来构造平衡二叉树。

它将数据按照升序或者降序排列,选择中间元素作为根节点,然后递归地对左子树和右子树进行构造。

这种方法保证了构造的树是一个平衡二叉树,从而提高了数据的查找、插入和删除等操作的效率。

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

平衡二叉树(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)平衡二叉树的显示采用中序遍历的方法输出,还可以根据输出数据是否有序验证对平衡二叉树的操作是否正确。

设计说明(一)ADTADT BalancedBinaryTree{数据对象D:D是具有相同特性的数据元素的集合。

各个数据元素均含有类型相同,可唯一标志的数据元素的关键字。

数据关系R:数据元素同属一个集合。

基本操作P:void R_Rotate(BSTree &p);初始条件:二叉树存在,且关键字插入到以*p为根的二叉树的左子树的左孩子上;操作结果:对以*p为根的二叉排序树作右旋处理void L_Rotate(BSTree &p);初始条件:二叉树存在,且关键字插入到以*p为根的二叉树的右子树的右孩子上;操作结果:对以*p为根的二叉排序树作左旋处理void LeftBalance(BSTree &T);初始条件:二叉树存在,且关键字插入到T所指节点为根的二叉树的左子树的右孩子上;操作结果:对以指针T所指结点为根的二叉树作左平衡旋转处理void RightBalance(BSTree &T);初始条件:二叉树存在,且关键字插入到T所指节点为根的二叉树的右子树的左孩子上;操作结果:对以指针T所指结点为根的二叉树作右平衡旋转处理bool InsertAVL(BSTree &T,int e,bool &taller);初始条件:T存在,且e与二叉树的原有关键字不同;操作结果:插入结点e平且平衡化;bool SearchBST(BSTree &T,int key);初始条件:T存在且元素key与某关键字相同;操作结果:查找元素key是否在树T中void PrintBST(BSTree T);初始条件:T存在操作结果:按中序遍历输出二叉树的元素void CreatBST(BSTree &T);初始条件:T为空操作结果:创建平衡二叉树,(注意:以输入-1为二叉树建立的结束)void LeftBalance_div(BSTree &p,int &shorter);初始条件:T存在操作结果:删除结点时左平衡旋转处理void RightBalance_div(BSTree &p,int &shorter);初始条件:T存在操作结果:删除结点时右平衡旋转处理void Delete(BSTree q,BSTree &r,int &shorter);初始条件:T存在且节点删除成功操作结果:删除结点int DeleteAVL(BSTree &p,int x,int &shorter);初始条件:操作结果:平衡二叉树的删除操作} ADT BalancedBinaryTree(二)算法思想1、查找在根指针T所指二叉排序树中递归地查找某关键字等于key的数据元素,若查找成功,则返回指向该数据元素结点的指针,否则返回空指针。

如果树T为空,则查找不成功,返回空指针;当树T非空时,如果根指针T所指数据元素的关键字等于key,则查找成功,返回根指针T,否则在左子树中继续查找,若还未找到,则继续在右子树中进行查找,直到找到该数据元素或树T为空为止。

//查找元素key是否在树T中bool SearchBST(BSTree &T,int key){if(!T) return false;else if(EQ(key,T->data)) return true;else if(LT(key,T->data)) return SearchBST(T->lchild,key);else return SearchBST(T->rchild,key);}2、插入(一)若T为空树,则插入一个数据元素为e的新节点作为T的根节点,树长高,树的深度增加1。

(二)若待插入的数据元素e与T的根节点的关键字相同,则不进行插入。

(三)若待插入的数据元素e小于根节点的关键字,且在T的左子树上不存在与e相等的数据元素,那么将e插入到T的左子树上。

下面就插入到左子树之后,就不同的情况进行处理:①若之前T的根节点的平衡因子为-1,将根节点的平衡因子变为0,T的深度不变;②若之前T的根节点的平衡因子为0,就将根节点的平衡因子变为1,T的深度增加;③若之前的T的根节点的平衡因子为1,那么当其左子树的根节点的平衡因子为1的时候,需要进行单向右旋处理,并且在右旋处理之后,将根节点和其右子树根节点的平衡因子改为0,树的深度不变;当其左子树的根节点的平衡因子为-1的时候,要进行先左后右的双向旋转平衡,并在旋转之后,修改根节点和其左右子树的根节点的平衡因子,树的深度不(四)若待插入的数据元素e大于根节点的关键字,且在T的右子树上不存在与e相等的数据元素,那么将e插入到T的右子树上。

下面就插入到右子树之后,就不同的情况进行处理:①若之前T的根节点的平衡因子为1,将根节点的平衡因子变为0,T的深度不变;②若之前T的根节点的平衡因子为0,就将根节点的平衡因子变为1,T的深度增加;③若之前的T的根节点的平衡因子为-1,那么当其右子树的根节点的平衡因子为-1的时候,需要进行单向左旋处理,并且在左旋处理之后,将根节点和其左子树根节点的平衡因子改为0,树的深度不变;当其右子树的根节点的平衡因子为1的时候,要进行先右后左的双向旋转平衡,并在旋转之后,修改根节点和其左右子树的根节点的平衡因子,树的深度不变。

//插入结点e,若T中不存在和e相同关键字的结点,则插入一个数据元素为e的新结点,并返回1,否则返回0bool InsertAVL(BSTree &T,int e,bool &taller){if(!T)//插入新结点,树"长高",置taller为true{T = (BSTree)malloc(sizeof(BSTNode));T->data = e;T->lchild = T->rchild =NULL;T->bf = EH; taller = true;else{if(EQ(e,T->data)) //树中已存在和有相同关键字的结点则不再插入{taller = false;printf("已存在相同关键字的结点\n");return 0;}if(LT(e,T->data)) //应继续在*T的左子树中进行搜索{if(!InsertAVL(T->lchild,e,taller))return 0;//未插入if(taller) //已插入到*T的左子树中且左子树"长高"{switch(T->bf) //检查*T的平衡度{case LH: //原本左子树比右子树高,需要作左平衡处理LeftBalance(T);taller = false; break;case EH: //原本左子树、右子等高,现因左子树增高而使树增高T->bf = LH;taller = true; break;case RH: //原本右子树比左子树高,现左、右子树等高T->bf = EH;taller = false; break;}}}else //应继续在*T的右子树中进行搜索{if(!InsertAVL(T->rchild,e,taller))return 0;//未插入if(taller) //已插入到*T的右子树中且右子树"长高"{switch(T->bf) //检查*T的平衡度{case LH: //原本左子树比右子树高,现左、右子树等高T->bf = EH; taller = false; break;case EH: //原本左子树、右子等高,现因右子树增高而使树增高T->bf = RH; taller = true; break;case RH: //原本右子树比左子树高,需要作右平衡处理RightBalance(T); taller = false; break;}}}}return 1;}//InsertAVL3、删除元素的删除,有三种情况,分别是:(1)被删除的结点是叶子;(2)被删除的结点只有左子树或者只有右子树;(3)被删除的结点既有左子树,也有右子树。

具体实现如下:int DeleteAVL(BSTree &p,int x,int &shorter) {int k;BSTree q;if(p==NULL){printf("不存在要删除的关键字!!\n");return 0;}else if(x<p->data)//在p的左子树中进行删除{k=DeleteAVL(p->lchild,x,shorter);if(shorter==1)LeftBalance_div(p,shorter);return k;}else if(x>p->data)//在p的右子树中进行删除{k=DeleteAVL(p->rchild,x,shorter);if(shorter==1)RightBalance_div(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(shorter==1)LeftBalance_div(p,shorter);p=q;}return 1;}}(三)数据结构本实验中平衡二叉树采用二叉链表的方式进行存储。

相关文档
最新文档