六、遍历序列还原树

一、遍历序列还原二叉树

由二叉树的先序序列和中序序列,或者中序序列和后序序列,可以唯一地还原一棵二叉树。
注意:由二叉树的先序序列和后序序列不能唯一地还原一棵二叉树。

1.1 还原二叉树的方法

先序序列和中序序列还原二叉树。
算法步骤: (先序找根, 中序分左右)
  1)先序序列的第一个字符为根。
  2)在中序序列中,以根为中心划分左右子树。
  3)还原左右子树。

 

 已知一棵二叉树的先序序列ABDECFG和中序序列DBEAFGC,画出这棵二叉树。

1.2 还原二叉树代码分析

函数设置三个参数: pre,mid,len。
pre、mid为指针类型,分别指向先序、中序序列的首地址;
len为序列的长度。

Btree pre_mid_createbtree(char *pre, char *mid, int len) // pre先序首地址, mid中序首地址
{
    if(len = 0)
    {
        return NULL;
    }
    char ch = pre[0]; // 先序中第一个节点为空
    int index = 0;
    while(mid[index] != ch) // 在中序中找到根的位置,根的左边为该节点的左子树,右边为右子树
    {
        index++;
    }
    Btree T = new Bnode;
    T->data = ch;
    T->lchild = pre_mid_createbtree(pre+1, mid, index);  // 创建左子树
    T->rchild = pre_mid_createbtree(pre+index+1, mid+index+1, len-index-1); // 创建右子树
    return T;
}

 

先序遍历和中序遍历还原二叉树秘籍:先序找根,中序分左右。
后序遍历和中序遍历还原二叉树秘籍:后序找根,中序分左右。

 

练习:已知一棵二叉树的后序序列DEBGFCA和中序序列DBEAFGC,画出这棵二叉树。

二、遍历序列还原树

树的先根遍历和后根遍历与其对应二叉树的先序遍历和中序遍历相同,先根据对应关系还原为二叉树,再把二叉树转换为树。

已知一棵树的先根遍历序列ABEFCDGIH和后根遍历序列EFBCIGHDA,画出这棵树。

 

三、遍历序列还原森林

森林的先序遍历和中序遍历与其对应二叉树的先序遍历和中序遍历相同,先根据对应关系还原为二叉树,再把二叉树转换为森林。

已知森林的先序遍历序列ABCDEFGHJI和中序遍历序列BCDAFEJHIG,画出该森林。

四、总结

 

五、遍历序列还原二叉树代码整合

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<string>
using namespace std;

typedef struct Bnode
{
    char data;
    struct Bnode *lchild, *rchild;
}Bnode, *BTree;

// 先序中序还原二叉树
BTree pre_mid_createBtree(char *pre, char *mid, int len)
{
    if (len == 0)
    {
        return NULL;
    }
    char ch = pre[0];  // 先序中的第一个节点为根
    int index = 0;
    while (mid[index] != ch) //在中序中找到根的位置,根的左边为该节点的左子树,右边为右子树
    {
        index++;
    }
    BTree T = new Bnode; // 创建根节点
    T->data = ch;
    T->lchild = pre_mid_createBtree(pre + 1, mid, index);  // 创建左子树
    T->rchild = pre_mid_createBtree(pre + index + 1, mid + index + 1, len - index - 1); //创建右子树
    return T;
}

// 中序后序还原二叉树
BTree pro_mid_createbtree(char *last, char *mid, int len)
{
    if (len == 0)
    {
        return NULL;
    }
    char ch = last[len - 1]; // 后序中最后一个节点为根
    int index = 0;
    while (mid[index] != ch)
    {
        index++;
    }
    BTree T = new Bnode;
    T->data = ch;
    T->lchild = pro_mid_createbtree(last, mid, index); // 创建左子树
    T->rchild = pro_mid_createbtree(last + index, mid + index + 1, len - index - 1);// 创建右子树
    return T;
}

// 先序遍历二叉树
void pre_order(BTree &T)
{
    if (T)
    {
        cout << T->data << "  ";
        pre_order(T->lchild);
        pre_order(T->rchild);
    }
}

// 后序遍历二叉树
void pro_order(BTree &T)
{
    if (T)
    {
        pro_order(T->lchild);
        pro_order(T->rchild);
        cout << T->data << "  ";
    }
}
int main()
{
    BTree T;
    int count;
    char pre[100], mid[100], last[100];
    cout << "1. 前序中序还原二叉树" << endl;
    cout << "2. 后序中序还原二叉树" << endl;
    cout << "0. 退出" << endl;
    int choose = -1;
    while (choose)
    {
        cout << "请选择: ";
        cin >> choose;
        switch (choose)
        {
        case 1:
            cout << "前序中序还原二叉树" << endl;
            cout << "请输入节点长度: ";
            cin >> count;
            cout << "请依次输入先序序列" << endl;
            for (int i = 0; i < count; i++)
            {
                cin >> pre[i];
            }
            cout << "请依次输入中序序列"<< endl;
            for (int i = 0; i < count; i++)
            {
                cin >> mid[i];
            }
            T = pre_mid_createBtree(pre, mid, count);
            cout << endl;
            cout << "二叉树还原成功, 输出其后序序列为: " << endl;
            pro_order(T);
            cout << endl;
            break;
        case 2:
            cout << "中序后序还原二叉树" << endl;
            cout << "请输入节点长度: ";
            cin >> count;
            cout << "请依次输入中序序列:"<< endl;
            for (int i = 0; i < count; i++)
            {
                cin >> mid[i];
            }
            cout << "请依次输入后序序列" << endl;
            for (int i = 0; i < count; i++)
            {
                cin >> last[i];
            }
            T = pro_mid_createbtree(last, mid, count);
            cout << endl;
            cout << "二叉树还原成功, 输出其先序序列为: " << endl;
            pre_order(T);
            cout << endl;
            break;
        default:
            break;
        }
    }
    return EXIT_SUCCESS;
}

 

posted on 2022-04-09 19:08  软饭攻城狮  阅读(245)  评论(0编辑  收藏  举报

导航