题目要求
设二叉树采用二叉链表存储结构,结点数据域为字符类型。编写程序,用先序递归遍历法建立二叉树的二叉链表存储结构。然后输入一个字符,输出该字符在先、中、后序遍历中的访问次序(访问次序从1开始)以及先、中、后序遍历结果。若输入的字符不在二叉树中,输出相应提示信息。要求程序可以反复输入字符并输出访问次序及遍历结果,直到输入某个特殊字符时结束程序。注意:输入单个字符时需对其后的换行符进行处理。
数据结构设计
用结构体建立二叉树的二叉链表结构。其中,data表示数据域,lchild表示左指针,rchild表示右指针,BiT表示二叉链表结构体指针类型变量,BiTNode表示二叉链表结构体类型变量。
算法设计简要描述
- 先序遍历建立二叉树:递归调用函数,不断读取字符,依次建立左子树和右子树,当读取到‘#’字符时,返回NULL指针,最终返回根结点指针。
- 查询字符是否在二叉树中:在while循环中,反复输入字符,依次输出先序、中序、后序遍历结果,并判断该字符是否在二叉树中。
程序代码
#include <iostream>
using namespace std;
typedef struct node //二叉链表
{
ElemTp data; //数据域
struct node *lchild, //左指针
*rchild; //右指针
}*BiT, BiTNode;
void visit(BiT e) //访问函数
{
if (e->data != NULL) //输出二叉树的数据域
cout << e->data << " ";
}
void preorder(BiT bt) //先序遍历二叉树
{
if (bt)
{
visit(bt); //访问根节点
preorder(bt->lchild); //递归调用遍历左子树
preorder(bt->rchild); //递归调用遍历右子树
}
}
void midorder(BiT bt) //中序遍历二叉树
{
if (bt)
{
midorder(bt->lchild); //递归调用遍历左子树
visit(bt); //访问根节点
midorder(bt->rchild); //递归调用遍历右子树
}
}
void lasorder(BiT bt) //后序遍历二叉树
{
if (bt)
{
lasorder(bt->lchild); //递归调用遍历左子树
lasorder(bt->rchild); //递归调用遍历右子树
visit(bt); //访问根节点
}
}
BiT crtPreBT() //先序递归遍历建立二叉树算法
{
BiT bt;
char ch;
ch = getchar();
if (ch == '#') //读到‘#’返回NULL指针
return NULL;
bt = new BiTNode(); //建立新的二叉树结点
bt->data = ch;
bt->lchild = crtPreBT(); //递归建立左子树
bt->rchild = crtPreBT(); //递归建立右子树
return bt;
}
void prefind(BiT bt, ElemTp c, int &k) //先序查询(bt为根节点,c为查询元素,k记录查询元素的位置)
{
if (!bt || k > 0) //bt为空,或者k>0,直接返回
return;
k--;
if (bt->data == c) //查询到了元素c,将k变为k的相反数
k = -k;
if (k > 0)
return;
prefind(bt->lchild, c, k); //递归查询左子树
prefind(bt->rchild, c, k); //递归查询右子树
}
void midfind(BiT bt, ElemTp c, int &k) //中序查询(bt为根节点,c为查询元素,k记录查询元素的位置)
{
if (!bt || k > 0) //bt为空,或者k>0,直接返回
return;
midfind(bt->lchild, c, k); //递归查询左子树
if (k > 0)
return;
k--;
if (bt->data == c) //查询到了元素c,将k变为k的相反数
k = -k;
midfind(bt->rchild, c, k); //递归查询右子树
}
void lasfind(BiT bt, ElemTp c, int &k) //后序查询(bt为根节点,c为查询元素,k记录查询元素的位置)
{
if (!bt || k > 0) //bt为空,或者k>0,直接返回
return;
lasfind(bt->lchild, c, k); //递归查询左子树
lasfind(bt->rchild, c, k); //递归查询右子树
if (k > 0)
return;
k--;
if (bt->data == c) //查询到了元素c,将k变为k的相反数
k = -k;
}
int main()
{
int pre_n, mid_n, las_n;
pre_n = mid_n = las_n = 0; //pre_n, mid_n, las_n分别记录先序、中序、后序中该元素的位置
ElemTp c;
BiT bt;
cout << "请输入先序遍历的字符序列: " << endl;
bt = crtPreBT();
cout << "先序遍历结点访问次序: " << endl;
preorder(bt);
cout << endl;
cout << "中序遍历结点访问次序: " << endl;
midorder(bt);
cout << endl;
cout << "后序遍历结点访问次序: " << endl;
lasorder(bt);
cout << endl;
cout << "请输入要查找的字符('#'结束): " << endl;
cin >> c;
while (c != '#') //输入'#'结束
{
prefind(bt, c, pre_n);
midfind(bt, c, mid_n);
lasfind(bt, c, las_n);
cout << "先序遍历结点访问次序: " << endl;
preorder(bt);
cout << endl;
cout << "中序遍历结点访问次序: " << endl;
midorder(bt);
cout << endl;
cout << "后序遍历结点访问次序: " << endl;
lasorder(bt);
cout << endl;
if (pre_n > 0 && mid_n > 0 && las_n > 0)
{
cout << "先序遍历中该字符的访问次序为: " << pre_n << endl;
cout << "中序遍历中该字符的访问次序为: " << mid_n << endl;
cout << "后序遍历中该字符的访问次序为: " << las_n << endl;
}
else
cout << "二叉树中不存在该字符" << endl;
pre_n = mid_n = las_n = 0;
cout << "请输入下一个要查找的字符('#'结束): " << endl;
cin >> c;
}
return 0;
}
示例
(1)程序输入:
先序序列:ABC##DE#G##F###
请输入要查找的字符('#'结束):A G #
程序输出
先序遍历:A B C D E G F
中序遍历:C B E G D F A
后序遍历:C G E F D B A
A: 先序遍历中该字符的访问次序:1
中序遍历中该字符的访问次序:7
后序遍历中该字符的访问次序:7
G: 先序遍历中该字符的访问次序:6
中序遍历中该字符的访问次序:4
后序遍历中该字符的访问次序:2
(2)程序输入:
先序序列:ABDF####C#E#G#H##
请输入要查找的字符('#'结束):H R #
程序输出
先序遍历:A B D F C E G H
中序遍历:F D B A C E G H
后序遍历:F D B H G E C A
H: 先序遍历中该字符的访问次序:8
中序遍历中该字符的访问次序:8
后序遍历中该字符的访问次序:4
R: 二叉树中不存在该字符