【数据结构】——求二叉树某结点在先序、中序、后序遍历中的访问次序

题目要求

设二叉树采用二叉链表存储结构,结点数据域为字符类型。编写程序,用先序递归遍历法建立二叉树的二叉链表存储结构。然后输入一个字符,输出该字符在先、中、后序遍历中的访问次序(访问次序从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 #


程序输出
先序遍历: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: 二叉树中不存在该字符

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343

推荐阅读更多精彩内容