平衡二叉树算法实现 c语言版 插入 删除
#include <stdio.h>
#include <malloc.h>
#include<stdlib.h>
#define EQ(a,b) ((a)==(b))
#define LT(a,b) ((a)<(b))
#define LQ(a,b) ((a)>(b))
#define LH +1 //左高
#define EH 0 //等高
#define RH -1 //右高
#define NULL 0
//http://1wangxiaobo@163.com
/////////////////////////// 定义结构体 ///////////////////////////
typedef struct BSTNode
{
int data;
int bf; //结点的平衡因子
struct BSTNode *lchild,*rchild;//左、右孩子指针
}BSTNode,*BSTree;
/////////////////////////// 函数声明 ///////////////////////////
void R_Rotate(BSTree &p); //对以*p为根的二叉排序树作右旋处理
void L_Rotate(BSTree &p); //对以*p为根的二叉排序树作左旋处理
void LeftBalance(BSTree &T); //对以指针T所指结点为根的二叉树作左平衡旋转处理
void RightBalance(BSTree &T);//对以指针T所指结点为根的二叉树作右平衡旋转处理
bool InsertAVL(BSTree &T,int e,bool &taller);//插入结点e
bool SearchBST(BSTree &T,int key);//查找元素key是否在树T中
void PrintBST(BSTree T,int m);//按树状打印输出二叉树的元素
void CreatBST(BSTree &T); //创建平衡二叉树,(注意:以输入-1为二叉树建立的结束)
void LeftBalance_div(BSTree &p,int &shorter);//删除结点时左平衡旋转处理
void RightBalance_div(BSTree &p,int &shorter);//删除结点时右平衡旋转处理
void Delete(BSTree q,BSTree &r,int &shorter);//删除结点
int DeleteAVL(BSTree &p,int x,int &shorter);//平衡二叉树的删除操作
/////////////////////////////////////////////////////////////////////
void main()
{
int input,search,m;
bool taller=false;
int shorter=0;
BSTree T,T1,T2;
T=(BSTree)malloc(sizeof(BSTNode));
T=T1=T2=NULL;
while(1)
{ system("cls");
printf(" ******************************************\n");
printf(" ╱◥██◣ *1.创建\t2.查找\t3.插入\t4.删除\t5.退出*\n");
printf("|田|田田│ ******************************************\n");
printf("╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬<平衡二叉树 >\n");
printf("请输入您所需的操作功能:\t");
scanf("%d",&input);getchar();
switch(input)
{
case 1:
CreatBST(T); break;
case 2:
printf("请输入你要查找的关键字");
scanf("%d",&search); getchar();
if(SearchBST(T,search)) printf("该二叉树中存在关键字%d,查找成功!\n",search);
else printf("查找失败!\n");
break;
case 3:
printf("请输入你要插入的关键字");
scanf("%d",&search); getchar();
InsertAVL(T,search,taller); m = 0;
PrintBST(T,m); break;
case 4:
printf("请输入你要删除的关键字");
scanf("%d",&search); getchar();
DeleteAVL(T,search,shorter);
m=0; PrintBST(T,m); break;
case 5:
printf("\t\tbyebye!\n");break;
default:printf("输入错误,请重新选择。");break;
}
if(input == 5) break;
printf("\t\t按任意键继续..."); getchar();
}
}
//对以*p为根的二叉排序树作右旋处理
void R_Rotate(BSTree &p)
{
BSTree lc;
lc = p->lchild; //lc指向的*p左子树根结点
p->lchild = lc->rchild; //rc的右子树挂接为*p的左子树
lc->rchild = p; p = lc; //p指向新的结点
}
//对以*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所指结点为根的二叉树作左平衡旋转处理
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作右旋平衡处理
}
}
//对以指针T所指结点为根的二叉树作右平衡旋转处理
void RightBalance(BSTree &T)
{
BSTree rc,ld;
rc = T->rchild; //rc指向*T的左子树根结点
switch(rc->bf) //检查*T的右子树的平衡度,并作相应平衡处理
{
case RH: //新结点插入在*T的右孩子的右子树上,要作单左旋处理
T->bf = rc->bf =EH;
L_Rotate(T); break;
case LH: //新结点插入在*T的右孩子的左子树上,要作双旋处理
ld = rc->lchild; //ld指向*T的右孩子的左子树根
switch(ld->bf) //修改*T及其右孩子的平衡因子
{
case LH: T->bf = EH; rc->bf = RH; break;
case EH: T->bf = rc->bf =EH; break;
case RH: T->bf = LH; rc->bf = EH; break;
}
ld->bf = EH;
R_Rotate(T->rchild);//对*T的右子树作左旋平衡处理
L_Rotate(T); //对*T作左旋平衡处理
}
}
//插入结点e,若T中存在和e相同关键字的结点,则插入一个数据元素为e的新结点,并返回1,否则返回0
bool 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;
}//switch(T->bf)
}//if
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;
}//switch(T->bf)
}//else
}//else
return 1;
}//InsertAVL
//查找元素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);
}
//按树状打印输出二叉树的元素,m表示结点所在层次,初次调用时m=o
void PrintBST(BSTree T,int m)
{
int i;
if(T->rchild) PrintBST(T->rchild,m+1);
for(i = 1; i<=m; i++)
printf(" ");//打印 i 个空格以表示出层次
printf("%d\n",T->data);//打印 T 元素,换行
if(T->lchild)
PrintBST(T->lchild,m+1);
}
//创建平衡二叉树,(注意:以输入-1为二叉树建立的结束)
void CreatBST(BSTree &T)
{
int e,m;
bool taller=false;
T = NULL;
printf("\n请输入关键字(以-1结束建立平衡二叉树):");
scanf("%d",&e);getchar();
while(e != -1)
{
InsertAVL(T,e,taller);
printf("\n请输入关键字(以-1结束建立平衡二叉树):");
scanf("%d",&e);getchar();taller=false;
}
m=0;
printf("平衡二叉树创建结束,横向打印出树状结构:\n");
if(T) PrintBST(T,m);
else printf("这是一棵空树.\n");
}
//删除结点时左平衡旋转处理
void LeftBalance_div(BSTree &p,int &shorter)
{
BSTree p1,p2;
if(p->bf==1) //p结点的左子树高,删除结点后p的bf减1,树变矮
{ p->bf=0; shorter=1; }
else if(p->bf==0)//p结点左、右子树等高,删除结点后p的bf减1,树高不变
{ p->bf=-1; shorter=0; }
else //p结点的右子树高
{
p1=p->rchild;//p1指向p的右子树
if(p1->bf==0)//p1结点左、右子树等高,删除结点后p的bf为-2,进行左旋处理,树高不变
{
L_Rotate(p);
p1->bf=1; p->bf=-1; shorter=0;
}
else if(p1->bf==-1)//p1的右子树高,左旋处理后,树变矮
{
L_Rotate(p);
p1->bf=p->bf=0; shorter=1;
}
else //p1的左子树高,进行双旋处理(先右旋后左旋),树变矮
{
p2=p1->lchild;
p1->lchild=p2->rchild; p2->rchild=p1; p->rchild=p2->lchild; p2->lchild=p;
if(p2->bf==0)
{ p->bf=0; p1->bf=0; }
else if(p2->bf==-1)
{ p->bf=1;p1->bf=0; }
else
{ p->bf=0;p1->bf=-1; }
p2->bf=0; p=p2; shorter=1;
}
}
}
//删除结点时右平衡旋转处理
void RightBalance_div(BSTree &p,int &shorter)
{
BSTree p1,p2;
if(p->bf==-1)
{ p->bf=0; shorter=1; }
else if(p->bf==0)
{ p->bf=1; shorter=0; }
else
{
p1=p->lchild;
if(p1->bf==0)
{
R_Rotate(p);
p1->bf=-1; p->bf=1; shorter=0;
}
else if(p1->bf==1)
{
R_Rotate(p);
p1->bf=p->bf=0; shorter=1;
}
else
{
p2=p1->rchild;
p1->rchild=p2->lchild; p2->lchild=p1; p->lchild=p2->rchild; p2->rchild=p;
if(p2->bf==0)
{ p->bf=0; p1->bf=0; }
else if(p2->bf==1)
{ p->bf=-1; p1->bf=0; }
else
{ p->bf=0; p1->bf=1; }
p2->bf=0; p=p2; shorter=1;
}
}
}
//删除结点
void Delete(BSTree q,BSTree &r,int &shorter)
{
if(r->rchild==NULL)
{
q->data=r->data; q=r;
r=r->lchild; free(q);
shorter=1;
}
else
{
Delete(q,r->rchild,shorter);
if(shorter==1)
RightBalance_div(r,shorter);
}
}
//平衡二叉树的删除操作
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;
}
}
平衡二叉树算法实现 c语言版 插入 删除的更多相关文章
- 排序算法总结(C语言版)
排序算法总结(C语言版) 1. 插入排序 1.1 直接插入排序 1.2 Shell排序 2. 交换排序 2.1 冒泡排序 2.2 快速排序 3. 选择 ...
- 最短路径-----迪杰斯特拉算法(C语言版)
原文:http://blog.csdn.net/mu399/article/details/50903876 转两张思路图非常好: 描述略 图片思路很清晰. Dijkstra不适用负权值,负 ...
- [算法] 常见排序算法总结(C语言版)
常见排序算法总结 本文对比较常用且比较高效的排序算法进行了总结和解析,并贴出了比较精简的实现代码,包括选择排序.插入排序.归并排序.希尔排序.快速排序等.算法性能比较如下图所示: 1 冒泡排序 基本原 ...
- 和我一起从0学算法(C语言版)(一)
第一章 排序 第一节 简化版桶排法 友情提示:此文章分享给所有小白,大牛请绕路! 生活中很多地方需要使用排序,价格的由低到高.距离的由远及近等,都是排序问题的体现.如果排序量较少,依靠个人能力很容易实 ...
- 7、滑动窗口套路算法框架——Go语言版
前情提示:Go语言学习者.本文参考https://labuladong.gitee.io/algo,代码自己参考抒写,若有不妥之处,感谢指正 关于golang算法文章,为了便于下载和整理,都已开源放在 ...
- 和我一起从0学算法(C语言版)(四)
第三章 搜索 深度优先搜索与宽度优先搜索 定义 深度优先搜索(DFS) 过程简要来说是对每一个可能的分支路径深入到不能再深入为止,而且每个节点只能访问一次. 宽度优先搜索(BFS) 不考虑结果的可能位 ...
- 和我一起从0学算法(C语言版)(三)
第二章 暴力求解(枚举法) 第一节 小学奥数题-程序求解 观察下面的加法算式: 祥 瑞 生 辉 + 三 羊 献 瑞 ------------------- 三 羊 生 瑞 气 ...
- 和我一起从0学算法(C语言版)(二)
第一章 排序 第三节 快速排序 快速排序是最常用的排序方法.快排运用的递归方法很有意思.掌握了这种排序方法可以在将来学习递归时更快入门.只是快排的思路与之前的排序方法相比较为复杂,再加担心上我的表达能 ...
- 红黑树的删除详解与思路分析——不同于教科书上的算法(dart语言实现)
对于红黑树的删除,看了数据结构的书,也看了很多网上的讲解和实现,但都不满意.很多讲解都是囫囵吞枣,知其然,不知其所以然,讲的晦涩难懂. 红黑树是平衡二叉树的一种,其删除算法是比较复杂的,因为删除后还要 ...
随机推荐
- gdal 1.9+python 2.7开发环境配置
最近项目使用Cesium平台基于WegGl做web地球,其中关于地形数据有一种支持格式为terrain的地形数据.这种格式可以通过一个python工具切dem来得到. 下面记录下配置gdal+pyth ...
- Linux第三方源
由于版权等各方面原因,很多时候在基础安装完Linux后,满多软件并不包含在yum(对于Ubuntu可能是apt-get)源中. 因此可以去下载第三方源,安装下载第三方软件.当然,如果习惯了源代码编译安 ...
- 完成端口(Completion Port)详解(超级长,超级清楚)
http://www.cnblogs.com/lancidie/archive/2011/12/19/2293773.html
- Android系统设置— android.provider.Settings
android.provider.Settings Intent intent = new Intent(android.provider.Settings.ACTION_SETTINGS); sta ...
- 宣布发布 Windows Azure ExpressRoute,宣告与 Level 3 建立全新的合作伙伴关系并推出关于其他 Azure 服务令人振奋的更新
在我们与世界各地的客户和合作伙伴交谈时,总会听到他们说,希望找到一个提供商帮助他们最大限度地发挥内部部署投资的作用并且能够利用云的灵活性.这是我们构建混合云策略和云操作系统愿景的基本原则.本着我 ...
- A2W和W2A :很好的多字节和宽字节字符串的转换宏
以前看<Window核心编程>,感觉多字节和宽字节之间还比较麻烦的,至少MultiByteToWideChar函数和WideCharToMultiByte函数有足够多的参数的意义让我们去理 ...
- HDU 3350 #define is unsafe
题目大意:给定一个只含有MAX和+操作的式子,求加法运行了多少次,其中MAX使用宏定义. 题解:注意一个规律,对于MAX(A,B)其中A中加a次,B中加b次若A>B,则加a*2+b次,否则a+b ...
- nginx-lua实现简单权限控制
1,依赖软件:nginx(openresty) mysql(存储用户表)redis(存储用户登录token,有效期1周) create table account( uid integer not n ...
- Spring MVC遭遇checkbox的问题解决方式
Spring MVC遭遇checkbox的问题是:当checkbox全不选时候,则该checkbox域的变量为null,不能动态绑定到spring的controller方法的入參上,并抛出异常. 解决 ...
- Objective-c 类接口 (@interface) (类定义)
在Objective-c中如何定义一个类呢?我们可以使用下面的格式进行表示: @interface 类名:父类名{ 变量定义; } 方法定义: @end; 下面给出一个实例: @interface P ...