平衡二叉树的演示
一、需求分析:
(1) 构建一个平衡二叉树并实现创建、插入、查找、删除、销毁等操作。每种操作均提示输入关键字。每次插入或删除一个结点后,更新平衡二叉树的显示。
(2) 平衡二叉树的显示采用凹入表现形式。
(3)输入的形式时数字,无论对功能的选择还是对数据的录入,都是以数字的形式进行输入,无需使用文件保存数据。
(4) 输出的形式时在dos界面进行输出,一旦检测到错误的输入就会报错提示用户从新输入。
(5)程序所能达到的功能:
A:创建一颗非空平衡二叉树
B:向平衡二叉树中添加结点
C:从平衡二叉树中删除结点
D:在平衡二叉树中查找结点
E:销毁平衡二叉树
F:输出打印一棵平衡二叉树
G:合并两棵平衡二叉树
H:分裂一颗平衡二叉树
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<conio.h>
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define OVERFLOW 0
#define LH +1 //左子树比右子树高
#define EH 0 //等高
#define RH -1 //右子树比左子树高
typedef int Status;
typedef int KeyType;
typedef struct{
KeyType key;
}RcdType;
typedef struct BBSTNode{
RcdType data;
int bf; //结点平衡因子
struct BBSTNode *lchild,*rchild;
}*BBSTree; //平衡二叉树
void CreatBBST(BBSTree &T); //构建一棵二叉平衡树
BBSTree SearchBBST(BBSTree T,KeyType Key); //二叉平衡树非递归查找
void R_Rotate(BBSTree &p); //对最小失衡子树p作右旋调整
void L_Rotate(BBSTree &p); //对最小失衡子树p作左旋调整
void LeftBalance(BBSTree &T); //左平衡处理操作
void RightBalance(BBSTree &T); //右平衡处理操作
Status InsertAVL(BBSTree &T,RcdType e,Status &taller); //将e插入到二叉树
Status DeleteAVL(BBSTree &T,KeyType key,Status &shorter); //删除值为key的结点
void MergeBBST(BBSTree &T1,BBSTree &T2); //合并两棵二叉树
void Split(BBSTree T,KeyType e,BBSTree &T1,BBSTree &T2); //分裂操作
void SplitBBST(BBSTree T,KeyType e,BBSTree &T1,BBSTree &T2); //防止在将二叉树T分裂好之前改变了T1或T2
void DestroyBBST(BBSTree &T); //销毁树
void PrintBBST(BBSTree &T,int lev); //凹入表形式显示方法
int InsertMain(BBSTree &T,int taller); //连续插入函数
void Start(BBSTree &T1,BBSTree &T2); //操作演示界面
int main(); //main函数
void CreatBBST(BBSTree &T){
//构建一棵二叉平衡树
int num = 0,i,taller = 0,temp;
RcdType e;
printf("输入结点个数:");
if(scanf("%d",&num)==1){
if(num>0){
printf("请输入结点值\n");
for(i = 0;i < num;i++){
printf("第%d个结点的值:",i+1);
temp = scanf("%d",&e.key);
if(temp==1)
InsertAVL(T,e,taller);
else{
printf("请规范输入!\n");
fflush(stdin);
i--;
}
}
printf("构建成功!\n");
}
else
printf("构建失败!\n");
}
else
printf("请规范输入!\n");
fflush(stdin);
}
BBSTree SearchBBST(BBSTree T,KeyType Key){
//二叉平衡树非递归查找
while(T!=NULL){
if(T->data.key==Key)
return T; //成功
else if(T->data.key>Key)
T = T->lchild; //在左子树中继续查找
else
T = T->rchild; //在右子树中继续查找
}
return NULL; //失败
}
void R_Rotate(BBSTree &p){
//对最小失衡子树p作右旋调整
BBSTree lc = p->lchild; //lc指向p结点的左孩子
p->lchild = lc->rchild; //lc结点的右子树置为p结点的左子树
lc->rchild = p; //置原根结点为lc结点的右孩子
p = lc; //p指向新的根结点
}
void L_Rotate(BBSTree &p){
//对最小失衡子树p作左旋调整
BBSTree rc = p->rchild; //rc指向p结点的右孩子
p->rchild = rc->lchild; //rc结点的左子树置为p结点的右子树
rc->lchild = p; //置原根结点为rc结点的左孩子
p = rc; //p指向新的根结点
}
void LeftBalance(BBSTree &T){
//左平衡处理操作
BBSTree lc,rd;
lc = T->lchild; //lc指向T的左孩子
switch(lc->bf){ //检查T的左子树的平衡因子,并作相应处理
case LH: //LL型,需右旋调整
T->bf = lc->bf = EH; R_Rotate(T); break;
//右旋后平衡因子等于0
case RH: //新结点插入在T的左孩子的右子树上属于LR型,双旋处理
rd = lc->rchild;
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作右旋调整
break;
}
}
void RightBalance(BBSTree &T){
//右平衡处理操作
BBSTree rc,ld;
rc = T->rchild; //lc指向T的右孩子
switch(rc->bf){ //检查T的右子树的平衡因子,并作相应处理
case RH: //RR型,需左旋调整
T->bf = rc->bf = EH; L_Rotate(T); break;
case LH: //新结点插入在T的右孩子的左子树上属于RL型,双旋处理
ld = rc->lchild;
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作左旋调整
}
}
Status InsertAVL(BBSTree &T,RcdType e,Status &taller){
//将e插入到二叉树
if(T==NULL){ //T为空,树长高
T=(BBSTree)malloc(sizeof(BBSTNode));
T->data = e;
T->bf = EH; T->lchild = NULL; T->rchild = NULL; taller = TRUE;
}
else if(e.key==T->data.key){ //树中已经存在和e相等的结点
taller = FALSE;
return FALSE; //未插入
}
else if(e.key < T->data.key){ //插入到左子树
if(FALSE==InsertAVL(T->lchild,e,taller))
return FALSE;
if(TRUE==taller){
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{ //插入到右子树
if(FALSE==InsertAVL(T->rchild,e,taller))
return FALSE;
if(TRUE==taller){
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 TRUE;
}
Status DeleteAVL(BBSTree &T,KeyType key,Status &shorter) {
//删除值为key的结点
if(T == NULL)
return FALSE;
if(T->data.key == key) {
BBSTree p = NULL;
if(T->lchild == NULL) { //被删结点的左子树为空
p = T;
T = T->rchild; //直接将被删结点的右子树顶上
free(p);
shorter = TRUE; //树变矮
}
else if(T->rchild == NULL) { //被删结点的右子树为空
p = T;
T = T->lchild;
free(p);
shorter = TRUE;
}
else { //被删结点左右子树都不为空
p = T->lchild;
while(p->rchild) //找左子树的最大值,与删除结点交换数据
p = p->rchild;
T->data.key = p->data.key;
DeleteAVL(T->lchild,p->data.key,shorter); //删除被替换的结点
if(shorter) { //如果树变矮,调整平衡因子
switch(T->bf) {
case LH:T->bf = EH; shorter = TRUE; break;
case EH:T->bf = RH; shorter = FALSE; break;
case RH: //删除的结点在左子树,如果本来是右高,右旋
RightBalance(T); break;
}
}
}
}
else if(key < T->data.key) { //在左子树中查找
if(FALSE == DeleteAVL(T->lchild,key,shorter))
return FALSE;
if(shorter) { //在左子树中删除,如果树变矮
switch(T->bf) {
case LH:T->bf = EH; shorter = TRUE; break;
case EH:T->bf = RH; shorter = FALSE; break;
case RH:
RightBalance(T); break;
}
}
}
else { //在右子树中查找
if(FALSE == DeleteAVL(T->rchild,key,shorter))
return FALSE;
if(shorter) { //在右子树中删除,如果树变矮
switch(T->bf) {
case LH:
LeftBalance(T); break;
case EH:T->bf = LH; shorter = FALSE; break;
case RH:T->bf = EH; shorter = TRUE; break;
}
}
}
return TRUE;
}
void MergeBBST(BBSTree &T1,BBSTree &T2){
//合并两棵二叉树
int taller = 0;
if(!T2)
return;
MergeBBST(T1,T2->lchild);
InsertAVL(T1,T2->data,taller);
MergeBBST(T1,T2->rchild);
//中序遍历插入
}
//分裂一棵二叉树成为两棵
void Split(BBSTree T,KeyType e,BBSTree &T1,BBSTree &T2){
//分裂操作
int taller = 0;
if(!T)
return ;
Split(T->lchild,e,T1,T2); //查找最左孩子
if(T->data.key > e)
InsertAVL(T2,T->data,taller);
else
InsertAVL(T1,T->data,taller);
Split(T->rchild,e,T1,T2);
//中序遍历插入
}
void SplitBBST(BBSTree T,KeyType e,BBSTree &T1,BBSTree &T2){
//防止在将二叉树T分裂好之前改变了T1或T2
BBSTree t1 = NULL,t2 = NULL;
Split(T,e,t1,t2);
DestroyBBST(T1);
DestroyBBST(T2); //将之前的树先销毁
T1 = t1;
T2 = t2;
}
void DestroyBBST(BBSTree &T){
//销毁树
if(T==NULL) return ;
DestroyBBST(T->lchild);
DestroyBBST(T->rchild);
free(T);
}
void PrintBBST(BBSTree &T,int lev){
//凹入表形式显示方法
int i;
if(T->rchild)
PrintBBST(T->rchild,lev+1);
for(i = 0;i < lev;i++)
printf(" ");
printf("%d\n",T->data.key);
if(T->lchild)
PrintBBST(T->lchild,lev+1);
}
int InsertMain(BBSTree &T,int taller){
//连续插入函数
int n = 0;
RcdType e;
while(scanf("%d",&e.key)==1){
if(InsertAVL(T,e,taller))
n++;
}
fflush(stdin);
return n;
}
void Start(BBSTree &T1,BBSTree &T2){
//操作演示界面
int cho=5,num,taller = 0,shorter = 0,temp;
RcdType e;
while(1){
system("cls");
printf("\n平衡二叉树操作的演示 \n");
printf("***********************************************************\n");
printf(" 平衡二叉树显示区 \n");
printf("T1树\n\n");
if(!T1)
printf("当前为空树\n");
else
PrintBBST(T1,1);
printf("\nT2树\n\n");
if(!T2)
printf(" 当前为空树\n");
else
PrintBBST(T2,1);
printf("\n***********************************************************\n");
printf("==========================================================\n");
printf("| T1树操作:1.创建 2.插入 3.查找 4.删除 5.销毁 11.分裂 |\n");
printf("| T2树操作:6.创建 7.插入 8.查找 9.删除 10.销毁 12.分裂 |\n");
printf("| 特殊操作:13.合并T1,T2 0.退出 |\n");
printf("==========================================================\n");
printf("输入你要进行的操作:");
temp = scanf("%d",&cho);
fflush(stdin); //输入多个字符,如果不清除缓冲区,那么就会进入死循环!
if(temp!=1){ //输入操作不成功
printf("请规范输入!\n");
printf("按任意键返回>>>\n");
getch(); continue;
}
switch(cho){
case 1:
if(T1)
printf("树不为空!\n");
else
CreatBBST(T1);
break;
case 2:
printf("输入要插入的值(输入任意非数字字符结束插入):");
if(num = InsertMain(T1,taller))
printf("成功插入了%d个结点!\n",num);
else
printf("插入失败!\n");
break;
case 3:
printf("请输入要查找关键字的值:");
temp = scanf("%d",&e.key);
fflush(stdin);
if(temp==1){
if(SearchBBST(T1,e.key))
printf("查找成功!\n");
else
printf("查找失败!\n");
}
else
printf("请规范输入!\n");
break;
case 4:
printf("请输入要删除关键字的值:");
temp = scanf("%d",&e.key);
fflush(stdin);
if(temp==1){
if(DeleteAVL(T1,e.key,shorter))
printf("删除成功!\n");
else
printf("删除失败!\n");
}
else
printf("请规范输入!\n");
break;
case 5:
DestroyBBST(T1);
T1 = NULL; break;
case 6:
if(T2)
printf("树不为空!\n");
else
CreatBBST(T2);
break;
case 7:
printf("入要插入的值(输入任意非数字字符结束插入):");
if(num = InsertMain(T2,taller))
printf("成功插入了%d个结点!\n",num);
else
printf("插入失败!\n");
break;
case 8:
printf("请输入要查找关键字的值:");
temp = scanf("%d",&e.key);
fflush(stdin);
if(temp==1){
if(SearchBBST(T2,e.key))
printf("查找成功!\n");
else
printf("查找失败!\n");
}
else
printf("请规范输入!\n");
break;
case 9:
printf("请输入要删除关键字的值:");
temp = scanf("%d",&e.key);
fflush(stdin);
if(temp==1){
if(DeleteAVL(T2,e.key,shorter))
printf("删除成功!\n");
else
printf("删除失败!\n");
}
else
printf("请规范输入!\n");
break;
case 10:
DestroyBBST(T2);
T2 = NULL; break;
case 11:
if(T1){
printf("请输入要分裂的中间值:");
temp = scanf("%d",&e.key);
fflush(stdin);
if(temp==1)
SplitBBST(T1,e.key,T1,T2);
else
printf("请规范输入!\n");
}
else
printf("树为空!\n");
break;
case 12:
if(T2){
printf("请输入要分裂的中间值:");
temp = scanf("%d",&e.key);
fflush(stdin);
if(temp==1)
SplitBBST(T2,e.key,T1,T2);
else
printf("请规范输入!\n");
}
else
printf("树为空!\n");
break;
case 13:
MergeBBST(T1,T2);
T2 = NULL; break;
case 0:
system("cls");
exit(0);
default:
printf("请规范输入!\n");
}
printf("按任意键返回>>>\n");
getch();
}
}
int main(){
BBSTree T1 = NULL;
BBSTree T2 = NULL;
Start(T1,T2);
return 0;
}
来源:CSDN
作者:戮漠
链接:https://blog.csdn.net/m0_46140702/article/details/104144073