【數據結構】——求二叉樹某結點在先序、中序、後序遍歷中的訪問次序

題目要求

設二叉樹採用二叉鏈表存儲結構,結點數據域爲字符類型。編寫程序,用先序遞歸遍歷法創建二叉樹的二叉鏈表存儲結構。而後輸入一個字符,輸出該字符在先、中、後序遍歷中的訪問次序(訪問次序從1開始)以及先、中、後序遍歷結果。若輸入的字符不在二叉樹中,輸出相應提示信息。要求程序能夠反覆輸入字符並輸出訪問次序及遍歷結果,直到輸入某個特殊字符時結束程序。注意:輸入單個字符時需對其後的換行符進行處理。node

數據結構設計

用結構體創建二叉樹的二叉鏈表結構。其中,data表示數據域,lchild表示左指針,rchild表示右指針,BiT表示二叉鏈表結構體指針類型變量,BiTNode表示二叉鏈表結構體類型變量。ios

算法設計簡要描述

  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算法

相關文章
相關標籤/搜索