二叉树层次序中序还原二叉树

我们知道,二叉树的层次次序序列和中序序列可以唯一确定一棵二叉树,现在我们要编写程序由二叉树的层次次序序列和中序序列还原一棵二叉树。
二叉树的三种遍历序列,前序中序后序均可递归定义,因此由前序中序还原二叉树,后序中序还原二叉树很容易用递归算法实现。但二叉树的层次次序序列并非递归定义的,所以用递归很难由层次次序序列和中序序列还原二叉树,必须使用新的方法
我们可以由层次次序的第一个元素找到二叉树的根节点,在中序序列中找到这个根节点,中序序列中该根节点的左侧右侧子序列分别为根节点左右子树的中序序列,如果左子树中序序列不为空,那么层次次序的第2个元素就是根节点左子树的根节点,此时如果右子树中序序列也不为空,层次徐第三个元素就是右子树根节点,如果左子树为空,但右子树不为空,那么层次次序的第二个元素就是右子树的根节点。直到左右子树根节点后,我们可以在根节点左右子树的中序序列中找到这个根节点,这样二叉树中序序列中根节点和根节点左右子树根节点把中序序列从左到右划分为四部分,第1部分根节点就是根节点右子树根节点在层次序中的下一个元素x,第二部分的根节点就是x1在层次序中的下一个元素x2,----以此类推可知四部分的根节点。根节点,根节点左右子树,以及以上四部分根节点把中序序列划分为8部分,第一部分根节点就是上述四部分的第4部分根节点在层次序中的后继元素----以此类推
按照以上步骤可以确定二叉树所有子树(包括二叉树本身在内)在中序序列中的根节点,这样二叉树就可以构建了
把以上描述总结出算法如下: 我们需要两个队列,队列inorder_of_subtree用于存放各子树中序序列,队列seq_tree_node_queue用于存放每一层子树的根节点指针
层次次序序列为字符串sequence 中序序列为字符串 inorder
算法开始:
初始化:在inorder中找到sequence[0]所在下标index,将字符串inorder[0, index-1]和inorder[index+1, inorder.size-1]加入队列inorder_of_subtree
新建代表节点sequence[0]的二叉树节点,指针Node指向该节点,将Node加入队列seq_tree_node_queue,同时令root = Node并置j = 1;
迭代:
while(seq_tree_node_queue.empty() == false)
从seq_tree_node_queue中出对一个由指针cur_tree_node指向的节点
从inorder_of_subtree中出队中序序列left_sub_inorder
从inorder_of_subtree中出队中序序列right_sub_inorder
if (left_sub_inorder为空串)
将空指针赋予cur_treenode left_child域
else
在left_sub_inorder中找到sequence[j]所在下标i
将left_sub_inorder[0,i-1]入队inorder_of_subtree
将left_sub_inorder[ i+1,left_sub_inorder.size-1]入队inorder_of_subtree
新建一个代表left_sub_inorder[i]的二叉树节点,并将其指针链入cur_tree_node 的 leftchild域,并将该指针入队seq_tree_node_queue
j = j+1
endif
if (right_sub_inorder为空串)
将空指针赋予cur_treenode right_child域
else
在right_sub_inorder中找到sequence[j]所在下标i
将right_sub_inorder[0,i-1]入队inorder_of_subtree
将right_sub_inorder[ i+1,right_sub_inorder.size-1]入队inorder_of_subtree
新建一个代表right_sub_inorder[i]的二叉树节点,并将其指针链入cur_tree_node 的 rightchild域,并将该指针入队seq_tree_node_queue
j = j+1
endif
endwhile
算法结束 后,root指向创建的二叉树的根节点
完整C++代码如下:

#include <deque>
#include <string>
#include <iostream>
#include <utility>
using namespace std;

struct BinaryTree
{
    char data;
    BinaryTree* leftchild = nullptr;
    BinaryTree* rightchild = nullptr;
    BinaryTree(char d) :data(d) {}
};

void outPutPre(BinaryTree* root)
{
    if (root != nullptr)
    {
        cout << root->data;
        outPutPre(root->leftchild);
        outPutPre(root->rightchild);
    }
}

void outPutPost(BinaryTree* root)
{
    if (root != nullptr)
    {
        outPutPost(root->leftchild);
        outPutPost(root->rightchild);
        cout << root->data;
    }
}

int main()
{
    string sequence = "ABCD";
    string inorder = "BDCA";
    deque<pair<string::size_type, string::size_type>> inorder_of_subtree;
    deque<BinaryTree*> seq_tree_node_queue;

    string::size_type index;
    for (index = 0; index < inorder.size(); ++index)
    {
        if (inorder[index] == sequence[0])
            break;
    }
    inorder_of_subtree.push_back(make_pair(1, index));
    inorder_of_subtree.push_back(make_pair(index + 2, inorder.size()));
    BinaryTree* root = new BinaryTree(sequence[0]);
    seq_tree_node_queue.push_back(root);
    string::size_type j = 1;

    while (seq_tree_node_queue.empty() == false)
    {
        BinaryTree* cur_tree_node = seq_tree_node_queue.front();
        seq_tree_node_queue.pop_front();
        pair<string::size_type, string::size_type> left_sub_inorder = inorder_of_subtree.front();
        inorder_of_subtree.pop_front();
        pair<string::size_type, string::size_type> right_sub_inorder = inorder_of_subtree.front();
        inorder_of_subtree.pop_front();

        if (left_sub_inorder.first <= left_sub_inorder.second)
        {
            string::size_type i = left_sub_inorder.first - 1;
            for (; i < left_sub_inorder.second; ++i)
            {
                if (inorder[i] == sequence[j])
                    break;
            }
            inorder_of_subtree.push_back(make_pair(left_sub_inorder.first, i));
            inorder_of_subtree.push_back(make_pair(i + 2, left_sub_inorder.second));
            cur_tree_node->leftchild = new BinaryTree(inorder[i]);
            seq_tree_node_queue.push_back(cur_tree_node->leftchild);
            ++j;
        }

        if (right_sub_inorder.first <= right_sub_inorder.second)
        {
            string::size_type i = right_sub_inorder.first - 1;
            for (; i < right_sub_inorder.second; ++i)
            {
                if (inorder[i] == sequence[j])
                    break;
            }
            inorder_of_subtree.push_back(make_pair(right_sub_inorder.first, i));
            inorder_of_subtree.push_back(make_pair(i + 2, right_sub_inorder.second));
            cur_tree_node->rightchild = new BinaryTree(inorder[i]);
            seq_tree_node_queue.push_back(cur_tree_node->rightchild);
            ++j;
        }
    }
    cout << "前序序列是:";
    outPutPre(root);
    cout << endl;
    cout << "后序序列是:";
    outPutPost(root);
    cout << endl;
}
  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值