- 实现功能:建立二叉树存储结构、求二叉树的先序遍历、求二叉树的中序遍历、求二叉树的后序遍历、求二叉树的层次遍历、求根到给定结点的路径。
- 设计要求:
数据结构:
typedef struct node{
char data; //数据域
struct node *lchild , *rchild; //左右孩子指针
}BinTNode, *BinTree; //树中结点类型
首先设计一个含有多个菜单项的主控菜单程序,然后再为这些菜单项配上相应的功能。
程序运行后,给出如下菜单项的内容和输入提示,使用数字0—6来选择菜单项,其它输入则不起作用:
1.建立二叉树存储结构
2.求二叉树的先序遍历
3.求二叉树的中序遍历
4.求二叉树的后序遍历
5.求二叉树的层次遍历
6.求给定结点的路径
0.退出系统
请选择0—6:
#include<stdio.h>
#include<string.h>
#include<conio.h> //内含getch()
#include<iostream>
#include<malloc.h> //内含malloc
typedef struct BinTNode{
char data;
struct BinTNode *lchild , *rchild;
}BinTNode, *BinTree; //树中结点类型
//链栈
typedef struct StackNode{
BinTree data;
struct StackNode *next;
}StackNode,*LinkStack;
void print();
void CreateBinTree(BinTree &T,int num,char c);
void InOrderTraverse(BinTree &T);
void MidOrderTraverse(BinTree &T);
void LastOrderTraverse(BinTree &T);
void LevelOrder(BinTree &T);
bool FindPath(BinTree &T,LinkStack &S,char x);
bool ReFindPath(BinTree &T,LinkStack &S,char x,int m0);
int NodeCount(BinTree &T);
//以下为链栈的操作
void InitStack(LinkStack &S);
void Push(LinkStack &S,BinTree e);
void Pop(LinkStack &S);
void Get(LinkStack &S);
BinTree tree;
LinkStack S;
int n=0,m=0; //n为所查询结点个数,m为查询路径循环次数
int main(){
while(1){
print();
char c = getch(); //getch()返回从stdin读取的字符的ASCII值,如:输入字符'0',它将返回48;
int num;
if(c>'6'||c<'0'){
printf("\n请输入0-6之内的数字!\n");
continue;
}
else{
//在C/C++中,可以将字符直接转换成整数
/*
num = c;
printf("%d\n",num); //输出49
*/
num = c-'0';
//printf("%d\n",num); //输出1
}
if(num==1){
printf("\n请输入你要输入的树序列:\n");
CreateBinTree(tree,0,0);
if(tree==NULL){
printf("树为空树,请重新建立");
}
else{
printf("\n创建树完毕!\n");
InOrderTraverse(tree);
}
}
else if(num==2){
if(tree==NULL){
printf("树为空树,请重新建立");
}
else{
printf("\n输出先序:");
InOrderTraverse(tree);
printf("\n");
}
}
else if(num==3){
if(tree==NULL){
printf("树为空树,请重新建立");
}
else{
printf("\n输出中序:");
MidOrderTraverse(tree);
printf("\n");
}
}
else if(num==4){
if(tree==NULL){
printf("树为空树,请重新建立");
}
else{
printf("\n输出后序:");
LastOrderTraverse(tree);
printf("\n");
}
}
else if(num==5){
if(tree==NULL){
printf("树为空树,请重新建立");
}
else{
printf("\n输出层序遍历:");
LevelOrder(tree);
printf("\n");
}
}
else if(num==6){
if(tree==NULL){
printf("树为空树,请重新建立");
}
else{
int nodecon=NodeCount(tree);
InitStack(S);
printf("\n请输入要查询的结点");
char ch;
ch=getch();
printf("%c",ch);
bool b;
m=0;
b=FindPath(tree,S,ch);
if(!b){
printf("\n未查询到目标结点");
}
else if(m<nodecon){
while(m<nodecon){
n++;
printf("\n-------\n");
Get(S);
int m0=m; //m0暂存m值
m=0; //m重新计数
ReFindPath(tree,S,ch,m0);
}
}
printf("\n--------\n");
Get(S);
}
}
else if(num==0){
break;
}
}
return 0;
}
void print()
{
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("* 0. 退出系统 *\n");
printf("---------------------------------------\n");
printf(" 请输入0-6选择功能:");
}
void CreateBinTree(BinTree &T,int num,char c)
{
//按先序次序输入二叉树中结点的值(一个字符),创建二叉链表表示的二叉树T
if(num==1)
printf("\n请输入%c的左孩子,#代表空:\n",c);
else if(num==2)
printf("\n请输入%c的右孩子,#代表空:\n",c);
char ch;
ch=getch();
printf("%c",ch);
if(ch=='#'){
T=NULL;
} //递归结束,建空树
else
{
T=new BinTNode; //生成根结点
T->data=ch;
CreateBinTree(T->lchild,1,T->data); //递归创建左子树
CreateBinTree(T->rchild,2,T->data); //递归创建右子树
}
}
void InOrderTraverse(BinTree &T)
{
//先序遍历二叉树T的递归算法
if(T)
{
printf("%c",T->data);
InOrderTraverse(T->lchild);
InOrderTraverse(T->rchild);
}
}
void MidOrderTraverse(BinTree &T)
{
//中序遍历二叉树T的递归算法
if(T)
{
MidOrderTraverse(T->lchild);
printf("%c",T->data);
MidOrderTraverse(T->rchild);
}
}
void LastOrderTraverse(BinTree &T)
{
//中序遍历二叉树T的递归算法
if(T)
{
LastOrderTraverse(T->lchild);
LastOrderTraverse(T->rchild);
printf("%c",T->data);
}
}
void LevelOrder(BinTree &Tree) {
if(Tree==NULL)
return;
BinTree s[100];
int front, rear; //front头指针,rear尾指针
front = rear = -1; //采用顺序队列,并假定不会发生溢出
s[++rear] = Tree;
while(front != rear){
BinTree q = s[++front]; //q为头指针所指,每经过一轮循环,收集头指针的左右孩子
printf("%c",q->data);
if (q->lchild)
s[++rear] = q->lchild;
if (q->rchild)
s[++rear] = q->rchild;
}
}
bool FindPath(BinTree &T,LinkStack &S,char x){ //用链栈
m++;
bool b=false;
if(T==NULL){
return false;
}
Push(S,T); //入栈
if(T->data == x){
return true;
}
//先去左子树找
if(T->lchild != NULL){
b = FindPath(T->lchild,S,x);
}
//左子树找不到并且右子树不为空的情况下才去找
if(!b && T->rchild != NULL){
b = FindPath(T->rchild,S,x);
}
//左右都找不到,弹出栈顶元素
if(!b){
Pop(S); //不符,出栈
}
return b;
}
bool ReFindPath(BinTree &T,LinkStack &S,char x,int m0){
m++;
bool b=false;
if(T==NULL){
return false;
}
Push(S,T); //入栈
if(T->data == x){
if(m<=m0){
}
else{
return true;
}
}
//先去左子树找
if(T->lchild != NULL){
b = ReFindPath(T->lchild,S,x,m0);
}
//左子树找不到并且右子树不为空的情况下才去找
if(!b && T->rchild != NULL){
b = ReFindPath(T->rchild,S,x,m0);
}
//左右都找不到,弹出栈顶元素
if(!b){
Pop(S); //不符,出栈
}
return b;
}
void InitStack(LinkStack &S){
S=NULL;
return;
}
void Push(LinkStack &S,BinTree e){
//在栈顶插入e
StackNode* p = (StackNode *)malloc(sizeof(StackNode));
p->data=e;
p->next=S;
S=p; //修改栈顶指针为p
return;
}
void Pop(LinkStack &S){
//删除S的栈顶元素
if(S==NULL){
return;
}
StackNode* p =S; //用p临时保存栈顶空间,以备释放
S=S->next; //修改栈顶指针
delete p; //释放原栈顶元素的空间
return;
}
void Get(LinkStack &S){
printf("\n");
while(1){
if(S!=NULL){
printf("%c",S->data->data);
Pop(S);
}
else{
break;
}
}
}
int NodeCount(BinTree &T){
if(T==NULL){
return 0;
}
else{
return NodeCount(T->lchild)+NodeCount(T->rchild)+1;
}
}