一、实验目的:
1、熟悉二叉树结点的结构和对二叉树的基本操作;
2、掌握对二叉树每一种操作的具体实现;
3、学会递归方法和非递归方法实现二叉树的运算某重操作。
二、实验内容:
1、建立一棵二叉树。
2、用递归算法对二叉树进行先序、中序和后序遍历。
3、用非递归算法对二叉树进行先序、中序和后序遍历。
三、实验要求:
编写实现二叉树建立和遍历的基本算法的函数,并在此基础上设计一个主程序完成如下功能:
⑴定义二叉树的二叉链表存储结构;
⑵以扩展先序遍历序列建立二叉树的二叉链表;
⑶用递归算法分别实现二叉树的先序、中序和后续遍历,并打印输出;
⑷用非递归算法分别实现二叉树的先序、中序和后续遍历,并打印输出;
⑸计算二叉树的高度;
⑹计算二叉树叶子节点的个数。
输入格式为用.代表空,0为结束符。例如:12..34..5..0
代码如下:
#include <stdio.h>
#include <stdlib.h>
#define MAXNODE 100
typedef char ElemType;
typedef struct BiTreeNode
{
ElemType data;
struct BiTreeNode *lchild;
struct BiTreeNode *rchild;
}BiTreeNode, *BiTree;
//创建二叉树
BiTree CreateBiTree(char str[])
{
BiTree bt;
char ch;
static int i = 0;
ch = str[i++];
if (ch == '.')
bt = NULL; //创建空树
else
{
bt = (BiTree)malloc(sizeof(BiTreeNode));
bt->data = ch; //创建根节点
bt->lchild = CreateBiTree(str); //创建左子树
bt->rchild = CreateBiTree(str); //创建右子树
}
return bt;
}
void PreOrder(BiTree bt) //bt为指向根结点的指针
{
if (bt != NULL)
{
printf("%c", bt->data); //访问根节点
PreOrder(bt->lchild); //先序遍历左子树
PreOrder(bt->rchild); //遍历右子树
}
}
void InOrder(BiTree bt)
{
if (bt != NULL)
{
InOrder(bt->lchild); //中序遍历左子树
printf("%c", bt->data); //访问根节点
InOrder(bt->rchild); //遍历右子树
}
}
void PostOrder(BiTree bt)
{
if (bt != NULL)
{
PostOrder(bt->lchild); //后序遍历左子树
PostOrder(bt->rchild); //遍历右子树
printf("%c", bt->data); //访问根节点
}
}
int BitreeLeaf(BiTree bt)
{
if (bt == NULL)
return 0;
if (bt->lchild == NULL && bt->rchild == NULL)
//只有一个根节点
return 1;
else
return (BitreeLeaf(bt->lchild) + BitreeLeaf(bt->rchild));
}
int max(int a, int b)
{
if (a > b)
{
return a;
}
else
{
return b;
}
}
int BitreeDepth(BiTree bt)
{
int d = 0, depthL, depthR; //depthL,depthR分别表示左右子树深度
if (bt == NULL)
return 0; //空树,深度为0
depthL = BitreeDepth(bt->lchild);
depthR = BitreeDepth(bt->rchild);
d = max(depthL, depthR);
return d + 1;
}
//非递归先序遍历
void preOrder(BiTree bt)
{
BiTree s[MAXNODE], p = bt;
int top = -1;
if (p == NULL)return;
do{
while (p != NULL)
{
if (top >= MAXNODE - 1)
{
printf("栈溢出\n");
return;
}
printf("%c", p->data);
s[++top] = p;
p = p->lchild;
}
if (top == -1)return;
else
{
p = s[top--];
p = p->rchild;
}
} while (p != NULL || top != -1);
}
//非递归中序遍历
void inOrder(BiTree bt)
{
BiTree s[MAXNODE], p = bt;
int top = -1;
if (p == NULL)return;
do{
while (p != NULL)
{
if (top >= MAXNODE - 1)
{
printf("栈溢出\n");
return;
}
s[++top] = p;
p = p->lchild;
}
if (top == -1)return;
else
{
p = s[top--];
printf("%c", p->data); //访问根节点
p = p->rchild;
}
} while (p != NULL || top != -1);
}
//非递归后序遍历
void postOrder(BiTree T)
{
BiTree s[MAXNODE];
int top = -1;
BiTree p = T, r = NULL;
while (p || top > -1)
{
if (p) { //走到最左边
s[++top] = p;
p = p->lchild;
}
else { //向右
p = s[top]; //取栈顶元素
if (p->rchild && p->rchild != r) { //右子树不空,且未陪访问
p = p->rchild; //转向右
s[++top] = p; //压栈
p = p->lchild; //再走到最左
}
else { //否则弹出栈,并访问
p = s[top--];//出栈,并获得栈顶元素
printf("%c", p->data);
r = p; //记录最近访问过的结点
p = NULL; //结点访问过,重置p指针
}
}
}
}
//菜单界面
void menu()
{
system("cls");
printf("\n");
printf("\t\t---------------欢迎使用二叉树的创建和遍历--------------------------------\n");
printf("\t\t|\t\t a 用递归算法分别实现二叉树的先序遍历 \t\t|\n");
printf("\t\t|\t\t b 用递归算法分别实现二叉树的中序遍历 \t\t|\n");
printf("\t\t|\t\t c 用递归算法分别实现二叉树的后续遍历 \t\t|\n");
printf("\t\t|\t\t d 用非递归算法分别实现二叉树的先序遍历 \t\t|\n");
printf("\t\t|\t\t e 用非递归算法分别实现二叉树的中序遍历 \t\t|\n");
printf("\t\t|\t\t f 用非递归算法分别实现二叉树的后续遍历 \t\t|\n");
printf("\t\t|\t\t g 计算二叉树的高度 \t\t|\n");
printf("\t\t|\t\t h 计算二叉树叶子节点的个数 \t\t|\n");
printf("\t\t|\t\t i 退出系统 \t\t|\n");
printf("\t\t-------------------------------------------------------------------------\n");
printf("\t\t请选择(a-i):");
}
int main()
{
BiTree bt;
//BiTree *p = (BiTree *)malloc(sizeof(BiTree));
int deepth, num = 0;
int quit = 0;
char arr[50];
int i = 0;
char select;
printf("以扩展先序遍历序列建立二叉树:");
scanf("%c", &arr[i]);
while (arr[i] != '0'&&i<50)
{
i++;
scanf("%c", &arr[i]);
}
bt = CreateBiTree(arr);
getchar();
while (1)
{
menu(); //调用子函数
scanf("%c", &select);
switch (select)
{
case 'a': printf("遍历结果为:");
PreOrder(bt);
printf("\n");
break;
case 'b': printf("遍历结果为:");
InOrder(bt);
printf("\n");
break;
case 'c': printf("遍历结果为:");
PostOrder(bt);
printf("\n");
break;
case 'd': printf("遍历结果为:");
preOrder(bt);
printf("\n");
break;
case 'e': printf("遍历结果为:");
inOrder(bt);
printf("\n");
break;
case 'f': printf("遍历结果为:");
postOrder(bt);
printf("\n");
break;
case 'g': deepth = BitreeDepth(bt);
printf("树的深度为:%d\n", deepth);
break;
case 'h': num = BitreeLeaf(bt);
printf("树的叶子结点个数为:%d\n", num);
break;
case 'i': quit = 1; break;
default:printf("请输入a~i之间的数字\n"); break;
}
if (quit == 1)
{
break;
}
printf("按任意键返回主菜单!\n");
getchar(); //提取到缓冲区中的回车键
getchar(); //起到暂停的作用
printf("程序结束!\n");
}
return 0;
}