实验8、二叉树的应用(简单易懂,注释超级全,代码可以直接运行)
(1)实验目的
通过该实验,使学生理解二叉树的链式存储,掌握二叉树的几种遍历算法,并通过该实验使学生理解递归的含义,掌握C语言编写递归函数的方法和注意事项。
(2)实验内容
实现教材中算法6.4描述的二叉树创建算法,在此基础上实现二叉树的先序、后序递归遍历算法、两种非递归中序遍历、层序遍历、求二叉树的深度。
(3)参考界面
(4)验收/测试用例
创建
输入 :ABC$$DE$G$$F$$$ ($表示空格)
该输入对应的树如图所示
先序 屏幕输出 A B C D E G F
后序 屏幕输出 C G E F D B A
中序 屏幕输出 C B E G D F A
(两种中序非递归还需看源代码)
层序 屏幕输出 A B C D E F G
深度 屏幕显示 深度为5
这个实验我当时写了一周左右,第一开始着手这个实验的时候,感觉手足无措,不知道怎么下手,在网上找了一篇程序后在不断的调整debug之后(网上有很多代码都是有bug的运行不起来😔)终于运行成功,于是拿着请教老师,老师并没有多看那个代码,给了我另一种解题思路,利用栈和队列结合起来来解决属的问题,先序和后序利用的是递归函数,很基本的操作,中序和层序遍历分别用的栈和队列来实现的,真的非常好,我晚上回去思考后一晚上就写出来了
我是当时老师带的所有学生中第一个写出来这个实验并通过的学生,有点装13了,给自己鼓个掌,🤭
话不多说,直接上代码吧(第一次写出来的程序就不贴上去的)
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
using namespace std;
#define error 0
#define overflow -2
#define false -3
#define ok 1
#define maxsize 100 //栈和队列的最大存储空间
typedef char TElemType;
//树的结构体
typedef struct BiTNode{
TElemType data;
struct BiTNode *lchild;
struct BiTNode *rchild;
}BiTNode,*BiTree;
typedef BiTree SElemType;
typedef BiTree QElemType;
//typedef char TElemType;
typedef int Status;
//栈结构体
typedef struct{
SElemType *top;
SElemType *base;
int stacksize;//栈可以用的最大容量
}SqStack;
//队列结构体
typedef struct QNode{
QElemType data;
struct QNode *next;
}QNode,*QueuePtr;
typedef struct{
QueuePtr front;
QueuePtr rear;
}LinkQueue;
//树的结构体
/*typedef struct BiTNode{
TElemType data;
struct BiTNode *lchild;
struct BiTNode *rchild;
}BiTNode,*BiTree; */
//栈的函数
//初始化栈
Status InitStack(SqStack &S)
{
S.base = (SElemType *)malloc(maxsize * sizeof(SElemType));//为栈申请空间
if(S.base == 0)
{
exit(overflow);
}
S.top = S.base;
S.stacksize = maxsize;
return ok;
}
//入栈函数
Status Push(SqStack &S,BiTree p)
{
if(S.base == 0)
{
return error;//栈未初始化!!
}
if(S.top - S.base == S.stacksize)
{
return false;
}
*S.top = p;//将地址入栈中
S.top++;//top指针上移
return ok;
}
//出栈函数
Status Pop(SqStack &S,BiTree &p)
{
if(S.base == 0)
{
return error;
}
if(S.base == S.top)
{
return false;
}
S.top--;
p = *S.top;
return ok;
}
//获取栈顶元素
Status TopElem(SqStack S,BiTree &p)
{
if(S.base == 0)
{
return error;
}
if(S.base == S.top)
{
return false;
}
S.top--;
p = *S.top;
return ok;
}
//队列函数
//初始化队列
Status InitQueue(LinkQueue &Q)
{
Q.front = (QueuePtr)malloc(sizeof(QNode));
if(Q.front == 0)
{
exit(overflow);
}
Q.rear = Q.front;
Q.front->next = 0;
return ok;
}
//入队
Status InserElem(LinkQueue &Q,BiTree p)
{
if(Q.front == 0)
{
return error;
}
QueuePtr q;
q = (QueuePtr)malloc(sizeof(QNode));
q->data = p;
q->next = 0;
Q.rear->next = q;
Q.rear = q;
return ok;
}
//出队
Status DelElem(LinkQueue &Q,BiTree &p)
{
if(Q.front == 0)
{
return error;
}
if(Q.front == Q.rear)
{
return false;
}
QueuePtr q;
q = Q.front->next;//指向首元结点
p = q->data;
Q.front->next = q->next;
if(q == Q.rear)//保留尾指针,防止尾指针丢失
{
Q.rear = Q.front;
}
free(q);
return ok;
}
//树函数
//先序创建树
Status CreatTree(BiTree &T)
{
char ch;
cout<<"请输入树中的元素:"<<endl;
cin>>ch;
if(ch == '$')
{
T = 0;
}
else{
T = (BiTree)malloc(sizeof(BiTNode));
if(T == 0)
{
exit(overflow);
}
T->data = ch;//为结点赋值
CreatTree(T->lchild);//构建左子树
CreatTree(T->rchild);//构建右子树
}
return ok;
}
//先序遍历
Status PreOrderTraverse(BiTree T)
{
if(T == 0)
{
return error;//空二叉树也是递归出口
}
cout<<T->data<<" ";
PreOrderTraverse(T->lchild);
PreOrderTraverse(T->rchild);
}
//后序遍历
Status PostOrderTraverse(BiTree T)
{
if(T == 0)
{
return error;//空二叉树也是递归出口
}
PostOrderTraverse(T->lchild);
PostOrderTraverse(T->rchild);
cout<<T->data<<" ";
}
//中序遍历1
Status InOrderTraverse(BiTree T)
{
if(T == 0)
{
return error;//空二叉树
}
SqStack S;
InitStack(S);
while((T != 0)||(S.base != S.top))
{
if(T != 0)
{
Push(S,T);
T = T->lchild;
}
else{
Pop(S,T);
cout<<T->data<<" ";
T = T->rchild;
}
}
return ok;
}
//中序遍历2
Status InOrder_Traverse(BiTree T)
{
if(T == 0)
{
return error;//空二叉树
}
SqStack S;
InitStack(S);
Push(S,T);
while(S.base != S.top)
{
while((TopElem(S,T) == ok)&&(T != 0))
{
Push(S,T->lchild);
}
Pop(S,T);
if(S.base != S.top)
{
Pop(S,T);
cout<<T->data<<" ";
Push(S,T->rchild);
}
}
return ok;
}
//二叉树深度
Status DepthTree(BiTree T)
{
if(T == 0)
{
return 0;//空二叉树也是递归出口
}
int m,n;
m = DepthTree(T->lchild);
n = DepthTree(T->rchild);
if(m > n)
{
return m + 1;
}
else{
return n + 1;
}
}
//层序遍历
Status LevelOrderTraverse(BiTree T)
{
if(T == 0)
{
return 0;//空二叉树也是递归出口
}
LinkQueue Q;
InitQueue(Q);
InserElem(Q,T);
while(Q.front != Q.rear)
{
DelElem(Q,T);
cout<<T->data<<" ";
if(T->lchild != 0)
{
InserElem(Q,T->lchild);
}
if(T->rchild != 0)
{
InserElem(Q,T->rchild);
}
}
return ok;
}
//主函数
int main()
{
SqStack S;
S.base = 0;
LinkQueue Q;
Q.front = 0;
BiTree T;
T = 0;
int n,m,i,j;
cout<<"*********************"<<endl;
cout<<"1 9 2 5 0 5 0 3 4 3"<<endl;
cout<<"1.创建二叉树"<<endl;
cout<<"2.前序遍历二叉树"<<endl;
cout<<"3.中序遍历二叉树1"<<endl;
cout<<"4.中序遍历二叉树2"<<endl;
cout<<"5.后序遍历二叉树"<<endl;
cout<<"6.层序遍历二叉树"<<endl;
cout<<"7.求二叉树深度"<<endl;
cout<<"输入一个负数退出菜单!"<<endl;
cout<<"*********************"<<endl;
do{
cout<<"请输入你的选择:"<<endl;
cin>>n;
switch(n)
{
case 1:
CreatTree(T);
cout<<endl;
break;
case 2:
PreOrderTraverse(T);
cout<<endl;
break;
case 3:
InOrderTraverse(T);
cout<<endl;
break;
case 4:
InOrder_Traverse(T);
cout<<endl;
break;
case 5:
PostOrderTraverse(T);
cout<<endl;
break;
case 6:
LevelOrderTraverse(T);
cout<<endl;
break;
case 7:
m = DepthTree(T);
cout<<"该二叉树的深度为:"<<m<<endl;
break;
default :
cout<<"请输入1~6的数!"<<endl;
break;
}
}while(n > 0);
}
下面又到了手把手展示数据的环节辣
这个实验弄清楚原理就会非常简单嗷,赠人玫瑰,手留余香,👍也是这样嗷