题目要求

设二叉树采用二叉链表存储结构,结点数据域为字符类型。编写程序,用先序递归遍历法建立二叉树的二叉链表存储结构。然后输入一个字符,输出该字符在先、中、后序遍历中的访问次序(访问次序从1开始)以及先、中、后序遍历结果。若输入的字符不在二叉树中,输出相应提示信息。要求程序可以反复输入字符并输出访问次序及遍历结果,直到输入某个特殊字符时结束程序。注意:输入单个字符时需对其后的换行符进行处理。

数据结构设计

用结构体建立二叉树的二叉链表结构。其中,data表示数据域,lchild表示左指针,rchild表示右指针,BiT表示二叉链表结构体指针类型变量,BiTNode表示二叉链表结构体类型变量。

算法设计简要描述

  1. 先序遍历建立二叉树:递归调用函数,不断读取字符,依次建立左子树和右子树,当读取到‘#’字符时,返回NULL指针,最终返回根结点指针。
  2. 查询字符是否在二叉树中:在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 #
image.png
程序输出
先序遍历: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
image.png
(2)程序输入
先序序列:ABDF####C#E#G#H##
请输入要查找的字符('#'结束):H R #
image.png
程序输出
先序遍历: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: 二叉树中不存在该字符
image.png


木格
4 声望0 粉丝