数据结构课程设计,含分裂和合并
运行环境:VS2017
#include<stdio.h>
#include<malloc.h>
#define OVERFLOW -1
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define LH 1 //左高
#define EH 0 //等高
#define RH -1 //右高
typedef int RcdType;
typedef int Status;
//存放输入数据的链表结构体
typedef struct ListNode {
RcdType data;
ListNode *next;
}ListNode, *List;
//平衡二叉树结构体
typedef struct BBSTNode {
RcdType data;
int bf;
BBSTNode *lchild, *rchild;
}BBSTNode, *BBSTree;
//栈结点结构体
typedef struct LSNode {
BBSTree data;
struct LSNode *next;
}LSNode, *LStack;
//链队列结构体
typedef struct LQNode {
BBSTree elem;
struct LQNode *next;
}LQNode, *QueuePtr;
//队列结点结构体
typedef struct {
QueuePtr front;
QueuePtr rear;
}LQueue;
//初始化一个链栈
Status InitStack_LS(LStack &S) {
S = NULL;
return OK;
}
//进栈
Status Push_LS(LStack &S, BBSTree e) {
LSNode *t;
t = (LSNode*)malloc(sizeof(LSNode));
if (NULL == t) return OVERFLOW;
t->data = e;
t->next = S;
S = t;
return OK;
}
//出栈
Status Pop_LS(LStack &S, BBSTree &e) {
LSNode *t;
if (S == NULL) return ERROR;
t = S;
e = t->data;
S = S->next;
return OK;
}
//获得栈顶元素
Status GetTop_LS(LStack S, BBSTree &e) {
if (NULL == S) return ERROR;
else {
e = S->data;
return OK;
}
}
//判断栈是否为空
Status StackEmpty_LS(LStack S) {
if (NULL == S) return TRUE;
else return FALSE;
}
//初始化链队列
void InitQueue_LQ(LQueue &Q) {
Q.front = NULL;
Q.rear = NULL;
}
//进队
Status EnQueue_LQ(LQueue &Q, BBSTree e) {
LQNode *p;
p = (LQNode*)malloc(sizeof(LQNode));
if (NULL == p)
return OVERFLOW;
p->elem = e;
p->next = NULL;
if (NULL == Q.front) Q.front = p; //e插入空队列
else Q.rear->next = p; //e插入非空队列
Q.rear = p; //队尾指针指向新的队尾
return OK;
}
//出队
Status DeQueue_LQ(LQueue &Q, BBSTree &e) {
LQNode *p;
if (NULL == Q.front)
return ERROR;
p = Q.front;
e = p->elem;
Q.front = p->next;
if (Q.rear == p) Q.rear = NULL;
free(p);
return OK;
}
//左旋调整
void L_Rotate(BBSTree &p) {
BBSTree rc = p->rchild;
p->rchild = rc->lchild;
rc->lchild = p;
p = rc;
}
//右旋调整
void R_Rotate(BBSTree &p) {
BBSTree lc = p->lchild;
p->lchild = lc->rchild;
lc->rchild = p;
p = lc;
}
//左平衡处理操作
void LeftBalance(BBSTree &T) {
BBSTree lc, rd;
lc = T->lchild;
switch (lc->bf) {
case LH: T->bf = lc->bf = EH; R_Rotate(T);break;//LL
case RH://LR
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);
break;
case EH:
T->bf = LH;
lc->bf = RH;
R_Rotate(T);
}
}
//右平衡处理操作
void RightBalance(BBSTree &T)
{
BBSTree rd, lc;
rd = T->rchild;
switch (rd->bf) {
case RH: T->bf = rd->bf = EH;//RR
L_Rotate(T);
break;
case LH: lc = rd->lchild;//RL
switch (lc->bf) {
case LH: T->bf = EH; rd->bf = RH; break;
case RH: T->bf = LH; rd->bf = EH; break;
case EH: T->bf = rd->bf = EH; break;
}
lc->bf = EH;
R_Rotate(T->rchild);
L_Rotate(T);
break;
case EH:
T->bf = RH;
rd->bf = LH;
L_Rotate(T);
break;
}
}
//平衡二叉树的深度
int BBSTreeDepth(BBSTree T) {
int ldepth, rdepth;
if (NULL == T)
return 0;
else {
ldepth = BBSTreeDepth(T->lchild);
rdepth = BBSTreeDepth(T->rchild);
return 1 + (ldepth > rdepth ? ldepth : rdepth);
}
}
//平衡二叉树的查找
Status SearchAVL(BBSTree T, RcdType x)
{
if (T == NULL)
return FALSE;
if (x == T->data)
return TRUE;
else if (x > T->data)
return SearchAVL(T->rchild, x);
else
return SearchAVL(T->lchild, x);
}
//平衡二叉树的插入操作
Status InsertAVL(BBSTree &T, RcdType e, Status &taller) {
if (NULL == T) {//T为空,树长高
T = (BBSTree)malloc(sizeof(BBSTNode));
T->data = e;
T->bf = EH;
T->lchild = NULL;
T->rchild = NULL;
taller = TRUE;
}
else if (e == T->data) {//已存在结点,插入失败
taller = FALSE;
return FALSE;
}
else if (e < T->data) {
if (FALSE == InsertAVL(T->lchild, e, taller))
return FALSE;
if (TRUE == taller) {
switch (T->bf) {
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) {
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, RcdType e, Status &shorter)
{
//当被删结点有两个孩子,其前驱结点是左孩子时flag=1
int flag = 0;
if (t == NULL) {
return FALSE;
}
else if (e == t->data) {
BBSTree q = NULL;
//该结点只有一个孩子,将左子树取代该结点
if (t->lchild == NULL) {
q = t;
t = t->rchild;
free(q);
shorter = TRUE;
}
else if (t->rchild == NULL) {
q = t;
t = t->lchild;
free(q);
shorter = TRUE;
}
//被删结点有两个孩子,则找到其前驱结点并将前驱结点的值赋,删除前驱结点
else {
q = t->lchild;
while (q->rchild)
q = q->rchild;
t->data = q->data;
if (t->lchild->data == q->data)
flag = 1;
DeleteAVL(t->lchild, q->data, shorter);
if (flag == 1) {
BBSTree r = t->rchild;
if (NULL == r)
t->bf = 0;
else {
if (r->bf == EH)
t->bf = -1;
else
RightBalance(t);
}
}
}
}
else if (e < t->data) {
if (!DeleteAVL(t->lchild, e, shorter))
return FALSE;
//删除完结点之后,重调结点的平衡因子
if (shorter && (flag == 0)) {
switch (t->bf) {
case LH:
t->bf = EH;shorter = TRUE;
break;
case EH:
t->bf = RH;shorter = FALSE;
break;
case RH:
//右平衡处理
RightBalance(t);
if (t->rchild->bf == EH)
shorter = FALSE;
else
shorter = TRUE;
break;
}
}
}
else if (e > t->data) {
//右子树中继续查找
if (!DeleteAVL(t->rchild, e, shorter))
return FALSE;
//重调结点的平衡因子
if (shorter && (flag == 0)) {
switch (t->bf) {
case LH:
LeftBalance(t);
if (t->lchild->bf == EH)
shorter = FALSE;
else
shorter = TRUE;
break;
case EH:
t->bf = LH;shorter = FALSE;
break;
case RH:
t->bf = EH;shorter = TRUE;
break;
}
}
if (flag == 1) {
int ldepth = BBSTreeDepth(t->lchild);
int rdepth = BBSTreeDepth(t->rchild);
t->bf = ldepth - rdepth;
}
}
return TRUE;
}
//根据输入的数据建一棵平衡二叉树
void MakeBBSTree(BBSTree &T) {
int a;
Status taller = TRUE;
scanf("%d", &a);
while (a != 0) {
InsertAVL(T, a, taller);
scanf("%d", &a);
}
}
//递归先序遍历
Status PreOrderTraverse(BBSTree T)
{
if (NULL == T) return OK;
printf("%d ", T->data);
PreOrderTraverse(T->lchild);
PreOrderTraverse(T->rchild);
}
//递归中序遍历
Status InOrderTraverse(BBSTree T)
{
if (NULL == T) return OK;
InOrderTraverse(T->lchild);
printf("%d ", T->data);
InOrderTraverse(T->rchild);
}
//递归后序遍历
Status PosOrderTraverse(BBSTree T)
{
if (NULL == T) return OK;
PosOrderTraverse(T->lchild);
PosOrderTraverse(T->rchild);
printf("%d ", T->data);
}
//层次遍历
void LevelOrderTraverse_I(BBSTree &T)
{
if (T == NULL) return;
BBSTree p = T;
LQueue q;
InitQueue_LQ(q);
printf("%d ", p->data);
EnQueue_LQ(q, p);
while (DeQueue_LQ(q, p)) {
if (p->lchild) {
printf("%d ", p->lchild->data);
EnQueue_LQ(q, p->lchild);
}
if (p->rchild) {
printf("%d ", p->rchild->data);
EnQueue_LQ(q, p->rchild);
}
}
}
//凹入表输出平衡二叉树
void PrintTree(BBSTree T, int nlayer)
{
if (T == NULL) return;
for (int i = 0; i < nlayer; i++) {
printf(" ");
if (i == nlayer - 1)
printf("|--- ");
}
printf("%d(%d)\n", T->data, T->bf);
PrintTree(T->lchild, nlayer + 1);
PrintTree(T->rchild, nlayer + 1);
}
//括号表示法输出平衡二叉树
void BraNotationPrint(BBSTree T) {
if (T == NULL) {
printf("#");
return;
}
printf("%d", T->data);
if (!T->lchild && !T->rchild)
return;
else {
printf("(");
if (T->lchild)
BraNotationPrint(T->lchild);
else
printf("#");
printf(",");
if (T->rchild)
BraNotationPrint(T->rchild);
else
printf("#");
printf(")");
}
}
//分割树
void SplitBBSTree(BBSTree T, BBSTree &T1, BBSTree &T2, int x)
{
Status taller = FALSE;
if (T->data <= x)
InsertAVL(T1, T->data, taller);
else
InsertAVL(T2, T->data, taller);
if (T->lchild) SplitBBSTree(T->lchild, T1, T2, x);
if (T->rchild) SplitBBSTree(T->rchild, T1, T2, x);
}
//合并树
void MergeBBSTree(BBSTree &T1, BBSTree &T2)
{
Status taller = TRUE;
if (T2 != NULL) {
MergeBBSTree(T1, T2->lchild);
InsertAVL(T1, T2->data, taller);
MergeBBSTree(T1, T2->rchild);
}
}
//求平衡二叉树的叶子结点
void leaves(BBSTree T)
{
if (T == NULL) return;
if (T->lchild == NULL && T->rchild == NULL)
printf("%d ", T->data);
leaves(T->lchild);
leaves(T->rchild);
}
//销毁平衡二叉树
void DestroyAVL(BBSTree &T)
{
if (T) {
DestroyAVL(T->lchild);
DestroyAVL(T->rchild);
free(T);
T = NULL;
}
}
void menu()
{
printf("****************************\n");
printf("* 1.建立平衡二叉树 *\n");
printf("* 2.插入结点 *\n");
printf("* 3.删除结点 *\n");
printf("* 4.查找结点 *\n");
printf("* 5.遍历平衡二叉树 *\n");
printf("* 6.求叶子结点 *\n");
printf("* 7.平衡二叉树的深度 *\n");
printf("* 8.合并平衡二叉树 *\n");
printf("* 9.分裂平衡二叉树 *\n");
printf("* 10.销毁平衡二叉树 *\n");
printf("* 11.更换平衡二叉树 *\n");
printf("* 0.退出程序 *\n");
printf("****************************\n");
}
int main()
{
int select, case2;
BBSTree T = NULL, T1 = NULL, T2 = NULL, T3 = NULL;
Status taller = TRUE;
printf("* 数据结构课程设计平衡二叉树 *\n");
while (1) {
menu();
printf("\n请选择:");
scanf("%d", &select);
switch (select)
{
case 0:
DestroyAVL(T);
DestroyAVL(T1);
DestroyAVL(T2);
return 0;
break;
case 1:
printf("请输入整型数据(0退出)\n");
MakeBBSTree(T);
break;
case 2:
printf("请输入插入的整型数据:");
scanf("%d", &case2);
if (SearchAVL(T, case2))
printf("插入失败\n");
else {
InsertAVL(T, case2, taller);
printf("插入成功\n");
}
break;
case 3:
printf("请输入删除的整型数据:");
scanf("%d", &case2);
if (SearchAVL(T, case2)) {
DeleteAVL(T, case2, taller);
printf("删除成功\n");
}
else
printf("无此数据,删除失败\n");
break;
case 4:
printf("请输入要查找的整型数据:");
scanf("%d", &case2);
if (SearchAVL(T, case2) == 0)
printf("无此整型数据\n");
else
printf("查找成功,存在%d\n", case2);
break;
case 5:
printf("\n前序遍历:");
PreOrderTraverse(T);
printf("\n中序遍历:");
InOrderTraverse(T);
printf("\n后序遍历:");
PosOrderTraverse(T);
printf("\n层次遍历:");
LevelOrderTraverse_I(T);
printf("\n括号表示法打印:");
BraNotationPrint(T);
printf("\n凹入表打印:\n");
PrintTree(T, 0);
break;
case 6:printf("\n叶子结点是:"); leaves(T); printf("\n"); break;
case 7:printf("\n树的深度是%d\n", BBSTreeDepth(T)); break;
case 8:
printf("请输第二棵树的整型数据:(0退出)\n");
MakeBBSTree(T3);
printf("\n凹入表打印:\n");
PrintTree(T, 0);
printf("\n凹入表打印:\n");
PrintTree(T3, 0);
MergeBBSTree(T, T3);
DestroyAVL(T3);
printf("合并后:\n");
PrintTree(T, 0); break;
case 9:
if (T == NULL) printf("空树,无法分割\n");
else {
int xx;
printf("输入x值:\n");
scanf("%d", &xx);
SplitBBSTree(T, T1, T2, xx);
printf("分割后:\n");
PrintTree(T1, 0);
PrintTree(T2, 0);
printf("请选择要操作的平衡二叉树:1 or 2\n");
while (1) {
scanf("%d", &xx);
DestroyAVL(T);
if (xx == 1) {
T = T1;
T1 = NULL;
DestroyAVL(T2);
break;
}
else if (xx == 2) {
T = T2;
T2 = NULL;
DestroyAVL(T1);
break;
}
else
printf("选择无效,重新输入:");
}
}
break;
case 10:
if (T == NULL) {
printf("空树,无法销毁\n");
}
else {
DestroyAVL(T);
if (T == NULL)
printf("销毁成功\n");
}
break;
default:
printf("输入错误,重新输入\n");
break;
}
}
}