#include<stdio.h>
typedef char ElemType;
#include<malloc.h>
#define MaxSize 50
typedef struct node
{
ElemType data;
struct node *lchild;
struct node *rchild;
} BTNode;
void CreateBTree(BTNode * &b,char * str)
{
BTNode * St[MaxSize],*p;//St数组作为顺序栈
int top=-1,k,j=0;//top为栈顶指针
char ch;
b=NULL;//初始时二叉链为空
ch=str[j];
while(ch!='\0')//遍历str中的每个字符
{
switch(ch)
{
case'(':top++;St[top]=p;k=1;break;//开始处理左孩子结点
case')':top--;break;//栈顶结点子树处理完毕
case',':k=2;break;//开始处理右孩子结点
default:p=(BTNode * )malloc(sizeof(BTNode));//创建一个结点,又p指向它
p->data=ch;//存放结点值
p->lchild=p->rchild=NULL;//左右指针都设置为空
if(b==NULL)//若尚未建立根结点
b=p;//p所指向结点作为根结点
else
{
switch(k)
{
case 1:St[top]->lchild=p;break;//新建结点作为栈顶结点的左孩子
case 2:St[top]->rchild=p;break;//新建结点作为栈顶结点的右孩子
}
}
}
j++;
ch=str[j];//继续遍历str
}
}//创建二叉树
void DispBTree(BTNode * b)
{
if(b!=NULL)
{
printf("%c",b->data);
if(b->lchild!=NULL||b->rchild!=NULL)
{
printf("(");//有孩子结点时才输出"("
DispBTree(b->lchild);//递归输出左子树
if(b->rchild!=NULL)
printf(",");//有右孩子结点时才输出","
DispBTree(b->rchild);//递归输出右子树
printf(")");//有孩子结点时才输出")"
}
}
}//输出二叉树;
int BTHeight(BTNode *b)
{
int lchildh, rchildh;
if (b == NULL)
return (0);
else
{
lchildh = BTHeight(b->lchild);
rchildh = BTHeight(b->rchild);
return (lchildh > rchildh) ? (lchildh + 1) : (rchildh + 1);
}
} //求二叉树高度
int Nodes(BTNode * b)
{
if(b==NULL)
return 0;
else
return Nodes(b->lchild)+Nodes(b->rchild)+1;
}//求所有结点个数
void DispLeaf(BTNode * b)
{
if(b!=NULL)
{
if(b->lchild==NULL&&b->rchild==NULL)
printf("%c",b->data);//访问叶子结点
DispLeaf(b->lchild);//输出右子树中的叶子结点
DispLeaf(b->rchild);//输出左子树的叶子结点
}
}//求叶子结点
void PreOrder(BTNode * b)
{
if(b!=NULL)
{
printf("%c",b->data);//访问根结点
PreOrder(b->lchild);//先序遍历左子树
PreOrder(b->rchild);//先序遍历右子树
}
} //先序遍历
void InOrder(BTNode * b)
{
if(b!=NULL)
{
InOrder(b->lchild);//中序遍历左子树
printf("%c",b->data);//访问根结点
InOrder(b->rchild);//中序遍历右子树
}
}//中序遍历
void PostOrder(BTNode * b)
{
if(b!=NULL)
{
PostOrder(b->lchild);//后序遍历左子树
PostOrder(b->rchild);//后序遍历右子树
printf("%c",b->data);//访问根结点
}
}//后序遍历
void LevelOrder(BTNode *b)
{
BTNode *p;
BTNode *qu[MaxSize]; // 定义一个队列数组
int front, rear; // 定义队列的头指针和尾指针
front = rear = 0; // 初始化队列头指针和尾指针为0
if (b != NULL) // 如果树不为空
{
rear = (rear + 1) % MaxSize; // 尾指针加1,使用循环队列的方式
qu[rear] = b; // 根节点入队
while (front != rear) // 队列不为空时循环
{
front = (front + 1) % MaxSize; // 头指针加1,使用循环队列的方式
p = qu[front]; // 出队一个节点
printf("%c", p->data); // 输出节点值
if (p->lchild != NULL) // 如果左孩子不为空
{
rear = (rear + 1) % MaxSize; // 尾指针加1,使用循环队列的方式
qu[rear] = p->lchild; // 左孩子入队
}
if (p->rchild != NULL) // 如果右孩子不为空
{
rear = (rear + 1) % MaxSize; // 尾指针加1,使用循环队列的方式
qu[rear] = p->rchild; // 右孩子入队
}
}
}
}
void DestroyBTree(BTNode * &b)
{
if(b!=NULL)
{
DestroyBTree(b->lchild);
DestroyBTree(b->rchild);
free(b);
}
}//销毁二叉树
int main()
{
BTNode *b;
char str[] = "A(B(D,E(G,H)),C(,F(K)))";
CreateBTree(b, str);
printf("该二叉树的括号表示法为:\n");
DispBTree(b);
printf("\n");
printf("该二叉树的高度为:%d\n", BTHeight(b));
printf("该二叉树的结点数为:%d\n", Nodes(b));
printf("该二叉树叶子节点数为:\n");
DispLeaf(b);
printf("\n");
printf("先序遍历的序列为:");
PreOrder(b);
printf("\n");
printf("中序遍历的序列为:");
InOrder(b);
printf("\n");
printf("后序遍历的序列为:");
PostOrder(b);
printf("\n");
printf("层序遍历的序列为:");
LevelOrder(b);
printf("\n");
printf("销毁二叉树\n");
DestroyBTree(b);
}
实验要求
有下图所示的二叉树,编写一个程序exp6-1.c,实现二叉树的各种基本运算和下面main函数中的每一步功能。
- 根据二叉树的括号表示法 A(B(D,E(G,H)),C(,F(K))),创建该二叉树的链式存储,并输出该二叉树;
- 求该二叉树的高度;
- 求该二叉树的结点数;
- 求该二叉树的叶子结点数;
- 输出二叉树的先序遍历的序列;
- 输出二叉树的中序遍历的序列;
- 输出二叉树的后序遍历的序列;
- 输出二叉树的层序遍历的序列;
- 销毁该二叉树。
运行结果如下