平衡二叉树(遍历,插入,删除)的C实现
/*
(2) 前序、中序、后序遍历二叉树 (递归)
(3) 前序、中序、后序遍历的非递归算法
(4) 层次遍历二叉树
(5) 在二叉树中查找给定关键字(函数返回值为成功1,失败0)
(6) 交换各结点的左右子树
(7) 求二叉树的深度
(8) 叶子结点数
(9) 删除某结点
*/
#include<stdio.h> //引用头文件stdio.h
#include<stdlib.h> //引用头文件stdlib.h
#include<malloc.h> //引用头文件malloc.h
#define MAXSIZE 100 //用#define定义全局变量MAXSIZE的值为100
#define OK 1 //用#define定义全局变量OK的值为1
#define ERROR 0 //用#define定义全局变量ERROR的值为0
typedef int Status; //定义Status为int类型来表示函数返回值状态
typedef int ElemType; //定义ElemType为int类型来表示元素类型
typedef struct BSTNode //定义平衡二叉树结构体
{
ElemType data; //结点存储的数据
int height; //结点的高度
struct BSTNode *lchild,*rchild; //左、右孩子指针
}BSTNode,*BSTree;
typedef BSTree Position; //定义Position为BSTree来表示节点树中位置
typedef struct //定义栈的结构体
{
BSTree *base; //在栈构造前和销毁后,base的值为NULL
BSTree *top; //栈顶指针
int stacksize; //当前已分配的存储空间,以元素为单位
}Stack;
typedef struct //定义队列的结构体
{
BSTree *front; //队头指针
BSTree *rear; //队尾指针
int queuesize; //当前已分配的存储空间,以元素为单位
}Queue;
Status InsertBST(BSTree &T,ElemType e); //实现树的节点的插入
Status PreOrderTraverse(BSTree T); //实现树的递归前序遍历
Status InOrderTraverse(BSTree T); //实现树的递归中序遍历
Status PostOrderTraverse(BSTree T); //实现树的递归后序遍历
Status AllOrderTraverse(BSTree T); //实现三种递归遍历的打印
Status NonPreOrder(BSTree T,Stack S); //实现树的非递归前序遍历
Status NonInOder(BSTree T,Stack S); //实现树的非递归中序遍历
Status NonPostOrder(BSTree T,Stack S); //实现树的非递归后序遍历
Status NonAllOrder(BSTree T,Stack S); //实现三种非递归遍历的打印
Status LevelTraverse(BSTree T,Queue Q); //实现二叉树的层次遍历
Status PostsSearch(BSTree T,ElemType e);//实现二叉树中给定关键字的查找
Status SwapSubtree(BSTree T); //实现结点左右子树的交换
int TreeDepth(BSTree T); //实现二叉树深度的求值
int TotalNodeNum(BSTree T); //实现二叉树总结点数的求值
int LeafNodeNum(BSTree T); //实现二叉树叶子结点数的求值
Status DeleteBST(BSTree &T,ElemType e); //实现树的节点的删除
int TreeHeight(BSTree T); //实现树的高度的求值
int Max(int a,int b); //实现两个数中求最大值
Position MinElemSearch(BSTree T); //实现最小元素的查找
BSTree LeftRotate(BSTree g); //实现二叉树一次右旋转操作
BSTree RightRotate(BSTree g); //实现二叉树一次左旋转操作
BSTree L_RRotate(BSTree g); //实现一次先左旋转再右旋转操作
BSTree R_LRotate(BSTree g); //实现一次先右旋转再左旋转操作
Status CreatStack(Stack &S); //实现栈的建立
Status CreatQueue(Queue &Q); //实现队列的建立
Status InsertBST(BSTree &T,ElemType e) //实现在二叉树中插入新结点的函数
{
if(T==NULL) //判断是否为空树,是则建建立一个根节点给树
{
T=(BSTree)malloc(sizeof(BSTNode));
if(!T) //判断该节点是否建立失败
return ERROR;
T->data=e;
T->height=0; //根节点时,高度为0
T->lchild=T->rchild=NULL;
}
else if(e<T->data) //如果输入的元素比节点数据小,则向左插入
{
InsertBST(T->lchild,e); //递归调用该函数本身
if(TreeHeight(T->lchild)-TreeHeight(T->rchild)==2)
{ //判断二叉树是否出现不平衡状态,是则进入该分支
if(e<T->lchild->data) //若输入的数据比左孩子结点的数据小,则进行右旋转
T=LeftRotate(T);
else //否则先进行左旋转再右旋转
T=L_RRotate(T);
}
}
else if(e>T->data) //如果输入的元素比节点数据大,则向右插入
{
InsertBST(T->rchild,e); //递归调用该函数本身
if(TreeHeight(T->rchild)-TreeHeight(T->lchild)==2)
{ //判断二叉树是否出现不平衡状态,是则进入该分支
if(e>T->rchild->data) //若输入的数据比右孩子结点的数据大,则进行左旋转
T=RightRotate(T);
else //否则先进行右旋转再左旋转
T=R_LRotate(T);
}
} //如果输入数据与节点数据相等,不需要进行操作
T->height=Max(TreeHeight(T->lchild),TreeHeight(T->rchild))+1;
return OK; //最后需要记录节点高度
}
Status PreOrderTraverse(BSTree T) //实现递归前序遍历函数
{
if(T!=NULL) //判断是否为空树
{
printf("%d ",T->data);
PreOrderTraverse(T->lchild);
PreOrderTraverse(T->rchild);
}
return OK;
}
Status InOrderTraverse(BSTree T) //实现递归中序遍历函数
{
if(T!=NULL) //判断是否为空树
{
InOrderTraverse(T->lchild);
printf("%d ",T->data);
InOrderTraverse(T->rchild);
}
return OK;
}
Status PostOrderTraverse(BSTree T) //实现递归后序遍历函数
{
if(T!=NULL) //判断是否为空树
{
PostOrderTraverse(T->lchild);
PostOrderTraverse(T->rchild);
printf("%d ",T->data);
}
return OK;
}
Status AllOrderTraverse(BSTree T) //实现各种递归遍历打印函数
{
printf("\n\t递归前序遍历如下:\n\t");
PreOrderTraverse(T);
printf("\n");
printf("\n\t递归中序遍历如下:\n\t");
InOrderTraverse(T);
printf("\n");
printf("\n\t递归后序遍历如下:\n\t");
PostOrderTraverse(T);
printf("\n");
return OK;
}
Status NonPreOrder(BSTree T,Stack S) //实现非递归前序遍历函数
{
while(S.base!=S.top||T!=NULL) //判断栈和树是否为空
{
while(T!=NULL) //向左子树一直循环到最左的节点
{
printf("%d ",T->data); //输出元素
*S.top++=T;
T=T->lchild;
}
T=*--S.top; //实现出栈
T=T->rchild; //转向右子树
}
return OK;
}
Status NonInOder(BSTree T,Stack S) //实现非递归中序遍历函数
{
while(S.base!=S.top||T!=NULL) //判断栈和树是否为空
{
while(T!=NULL) //向左子树一直循环到最左的节点
{
*S.top++=T;
T=T->lchild;
}
T=*--S.top; //实现出栈
printf("%d ",T->data); //输出元素
T = T->rchild; //转向右子树
}
return OK;
}
Status NonPostOrder(BSTree T,Stack S) //实现非递归后序遍历函数
{
BSTree temp=NULL; //定义临时变量,用来标记刚刚访问过的节点
while(S.base!=S.top||T!= NULL) //判断栈和树是否为空
{
while(T!=NULL) //向左子树一直循环到最左的节点
{
*S.top++=T;
T=T->lchild;
}
T=*(S.top-1); //取栈顶节点
if(T->rchild==NULL||T->rchild==temp)
{ //如果该节点没有右孩子或者其右孩子刚刚被访问过
printf("%d ",T->data); //输出元素
S.top--; //已访问,使其出栈
temp=T; //标记为刚刚访问过
T=NULL; //若遍历完以该节点为根的子树,且栈空,则结束,否则继续
}
else
T=T->rchild; //转向右子树
}
return OK;
}
Status NonAllOrder(BSTree T,Stack S) //实现各种非递归遍历打印函数
{
printf("\n\t非递归前序遍历如下:\n\t");
CreatStack(S);
NonPreOrder(T,S);
printf("\n");
printf("\n\t非递归中序遍历如下:\n\t");
CreatStack(S);
NonInOder(T,S);
printf("\n");
printf("\n\t非递归后序遍历如下:\n\t");
CreatStack(S);
NonPostOrder(T,S);
printf("\n");
return OK;
}
Status LevelTraverse(BSTree T,Queue Q) //实现层次遍历函数
{
if(T!=NULL)
{
*Q.rear++=T;
while(Q.front!=Q.rear) //判断队列是否为空
{
if(T->lchild!=NULL) //判断左子树是否为空
*Q.rear++=T->lchild; //左子树进队
if(T->rchild!=NULL) //判断右子树是否为空
*Q.rear++=T->rchild; //右子树进队
T=*Q.front++; //实现出队操作
printf("%d ",T->data);
T=*Q.front; //此时的队头元素
}
}
return OK;
}
Status PostsSearch(BSTree T,ElemType e) //实现在二叉树中查找给定关键字函数
{
if(T!=NULL) //判断二叉树是否为空
{
if(e==T->data) //判断查找值是否与节点数据相等
return OK;
else if(e<T->data)
return PostsSearch(T->lchild,e);//查找值小于节点数据,则进入左子树查找
else
return PostsSearch(T->rchild,e);//查找值大于节点数据,则进入右子树查找
}
else
return ERROR;
}
Status SwapSubtree(BSTree T) //实现交换各结点的左右子树函数
{
BSTree temp; //定义临时变量
if(T!=NULL) //判断二叉树是否为空
{
temp=T->lchild;
T->lchild=T->rchild;
T->rchild=temp;
SwapSubtree(T->lchild);
SwapSubtree(T->rchild);
}
return OK;
}
int TreeDepth(BSTree T) //实现求二叉树的深度函数
{
int deep,ldeep=0,rdeep=0;
if(T!=NULL) //判断二叉树是否为空
{
ldeep=TreeDepth(T->lchild);
rdeep=TreeDepth(T->rchild);
deep=Max(ldeep,rdeep)+1;
}
else return 0;
return deep;
}
int TotalNodeNum(BSTree T) //实现统计总的结点数函数
{
int sum=0,lsum=0,rsum=0;
if(T!=NULL) //判断二叉树是否为空
{
lsum=TotalNodeNum(T->lchild);
rsum=TotalNodeNum(T->rchild);
sum=lsum+rsum+1;
return sum;
}
else return 0;
}
int LeafNodeNum(BSTree T) //实现统计叶子结点数函数
{
int dot=0,ldot=0,rdot=0;
if(T!=NULL) //判断二叉树是否为空
{
if(T->lchild==NULL&&T->rchild==NULL) //判断是否只含有一个节点
dot=1;
else
{
ldot=LeafNodeNum(T->lchild);
rdot=LeafNodeNum(T->rchild);
dot=ldot+rdot;
}
}
else return 0;
return dot;
}
Status DeleteBST(BSTree &T,ElemType e) //实现在二叉树中删除某结点的函数
{
Position temp; //定义临时变量
if(T==NULL) //判断二叉树是否为空
return ERROR;
else if(e<T->data) //需要删除的数据比节点数据小的情况
return DeleteBST(T->lchild,e); //继续调用函数本身进入左子树查找
else if(e>T->data) //需要删除的数据比节点数据大的情况
return DeleteBST(T->rchild,e); //继续调用函数本身进入右子树查找
else //即需要删除的数据与节点数据相等的情况
{
if(T->lchild!=NULL&&T->rchild!=NULL)
{ //左右孩子都存在的情况
temp=MinElemSearch(T->rchild); //在右子树中找到最小的节点
T->data=temp->data; //用找到的最小节点的数据代替要删除的节点的数据
DeleteBST(T->rchild,T->data); //删除右子树刚刚找到的最小的节点
}
else //有一个孩子或者没有孩子的情况
{
temp=T;
if(T->lchild==NULL) //判断是否没有孩子的情况
T=T->rchild;
else if(T->rchild==NULL) //判断是否有一个孩子的情况
T=T->lchild;
free(temp);
}
return OK;
}
}
int TreeHeight(BSTree T) //实现求树的高度的函数
{
if(T==NULL) //判断二叉树是否为空
return -1;
else
return T->height;
}
int Max(int a,int b) //实现求较大值的函数
{
return a>b?a:b; //三元运算符,哪个值大返回哪个
}
Position MinElemSearch(BSTree T) //实现查找最小元素的函数
{
if(T==NULL) //判断二叉树是否为空
return NULL;
else if(T->lchild==NULL) //判断是否为没有子树的情况
return T;
else
return MinElemSearch(T->lchild);
}
/*
100 85
/ \ 右旋 / \
85 120 ------ -> 60 100
/ \ \ / \
60 90 80 90 120
\
80
*/
BSTree LeftRotate(BSTree g) //实现树的向右旋转函数
{
BSTree temp;
temp=g->lchild;
g->lchild=temp->rchild;
temp->rchild=g;
temp->height=Max(TreeHeight(temp->lchild),g->height)+1;
g->height=Max(TreeHeight(g->lchild),TreeHeight(g->rchild))+1;
return temp; //返回新的根节点
}
/*
80 90
/ \ 左旋 / \
60 90 ---- -> 80 120
/ \ / \ /
85 120 60 85 100
/
100
*/
BSTree RightRotate(BSTree g) //实现树的向左旋转函数
{
BSTree temp;
temp=g->rchild;
g->rchild=temp->lchild;
temp->lchild=g;
g->height=Max(TreeHeight(g->lchild),TreeHeight(g->rchild))+1;
temp->height=Max(TreeHeight(g->rchild),g->height)+1;
return temp; //返回新的根节点
}
/*
100 100 90
/ \ 左旋 / \ 右旋 / \
80 120 ------> 90 120 ------> 80 100
/ \ / / \ \
60 90 80 60 85 120
/ / \
85 60 85
*/
BSTree L_RRotate(BSTree g) //实现树的向左旋转再向右旋转函数
{
g->lchild=RightRotate(g->lchild); //先左旋转
return LeftRotate(g); //再右旋转
}
/*
80 80 85
/ \ 右 旋 / \ 左 旋 / \
60 100 ------> 60 85 -------> 80 100
/ \ \ / / \
85 120 100 60 90 120
\ / \
90 90 120
*/
BSTree R_LRotate(BSTree g) //实现树的向右旋转再向左旋转函数
{
g->rchild=LeftRotate(g->rchild); //先右旋转
return RightRotate(g); //再左旋转
}
Status CreatStack(Stack &S) //实现栈的建立函数
{
S.base=(BSTree*)malloc(MAXSIZE*sizeof(BSTree));
if(!S.base) //判断是否建立失败
return ERROR;
S.top=S.base;
S.stacksize=MAXSIZE;
return OK;
}
Status CreatQueue(Queue &Q) //实现队列的建立函数
{
Q.front=(BSTree*)malloc(MAXSIZE*sizeof(BSTree));
if(!Q.front) //判断是否建立失败
return ERROR;
Q.rear=Q.front;
Q.queuesize=MAXSIZE;
return OK;
}
int main() //主函数
{
ElemType k,e,d;
int i,n,ch;
char c;
BSTree T=NULL;
Stack S;
Queue Q;
printf("\n\t运行本程序需要先构造一个二叉树!\n");
printf("\n\t请输入需要插入的元素个数:");
scanf("%d",&n);
if(n==0)
{
printf("\n\t成功创建一个空二叉树!",n);
c=getchar(); //用来吸收多余字符
c=getchar(); //用来吸收多余字符
}
else
{
printf("\n\t请输入要插入的%d个元素:",n);
for(i=0;i<n;i++) //连续输入n个元素
{
scanf("%d",&e);
InsertBST(T,e); //插入元素
}
printf("\n\t成功创建该二叉树!",n);
c=getchar(); //用来吸收多余字符
c=getchar(); //用来吸收多余字符
}
while(1) //进入程序的循环
{
system("cls"); //实现清屏处理
printf(" ☆ 实现平衡二叉树的各种算法 ☆ \n");
printf(" \n");
printf(" ◆◆◆◆◆◆◆◆◆◆◆◆ 请从下面的操作中选择一项 ◆◆◆◆◆◆◆◆◆◆◆◆◆\n");
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(" ◆ ◆ 0.退出本程序 ◆\n");
printf(" ◆ ◆\n");
printf(" ◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆\n");
printf("\n\t你的选择是:");
scanf("%d",&ch);
switch(ch) //进入选择
{
case 1: //调用插入结点的函数
printf("\n\t请输入你想要插入的元素:");
scanf("%d",&e);
if(InsertBST(T,e)==OK)
printf("\n\t成功插入元素%d!\n",e);
else
printf("\n\t插入元素%d失败!\n",e);
break;
case 2: //调用打印各种递归遍历的函数
printf("\n\t平衡二叉树的各种递归遍历如下:\n");
AllOrderTraverse(T);
break;
case 3: //调用打印各种非递归遍历的函数
printf("\n\t平衡二叉树的各种非递归遍历如下:\n");
NonAllOrder(T,S);
break;
case 4: //调用打印层次遍历的函数
printf("\n\t平衡二叉树的层次遍历如下:\n\t");
CreatQueue(Q); //创建队列
LevelTraverse(T,Q);
printf("\n");
break;
case 5: //调用关键字查找的函数
printf("\n\t请输入你想要查找的关键字:");
scanf("%d",&k);
if(PostsSearch(T,k)==OK) //返回查找的值,成功返回1,失败则返回0
printf("\n\t成功找到关键字%d!\n",k);
else
printf("\n\t没有找到关键字%d!\n",k);
break;
case 6: //调用转换子树的函数
if(SwapSubtree(T)==OK)
printf("\n\t成功交换左右子树!\n");
else
printf("\n\t交换左右子树失败!\n");
break;
case 7: //调用求二叉树深度的函数
printf("\n\t平衡二叉树的深度是:");
printf("%d\n",TreeDepth(T));
break;
case 8: //调用统计树结点数的函数
printf("\n\t平衡二叉树的总结点数是:");
printf("%d\n",TotalNodeNum(T));
printf("\n\t平衡二叉树的叶子结点数是:");
printf("%d\n",LeafNodeNum(T));
break;
case 9: //调用删除结点的函数
printf("\n\t请输入你想要删除的元素:");
scanf("%d",&d);
if(DeleteBST(T,d)==OK)
printf("\n\t成功删除元素%d!\n",d);
else
printf("\n\t删除失败,没有找到元素%d!\n",d);
break;
case 0: //输入0,则推出本程序
return 0;
break;
default: //如果输入非法字符,则进入该分支
c=getchar(); //用来吸收多余字符
printf("\n\a\t输入错误,请重新输入!\n");
break;
}
scanf("%c",&c); //用来吸收多余字符
printf("\n\t按任意键继续,或按“n”退出!你的选择是:");
scanf("%c",&c);
if(c=='n')
return 0;
}
return 0;
}