通过树的先序和中序遍历序列来构造二叉树

题目:给出一棵二叉树的先序和中序遍历的序列,构造出该二叉树。

思路一:采用分治法。

1)取先序遍历序列的第一个值,用该值构造根结点,,然后在中序遍历序列中查找与该元素相等的值,这样就可以把序列分为三部分:左子树(如果有)、根结点和右子树(如果有)。

2)将两个序列都分成三部分,这样就分别形成了根结点的左子树和右子树的先序遍历和后序遍历的序列。

3)重复1)和2)步骤,直至所有结点都处理完就可以完整构成一颗二叉树了。

根据分治法构造二叉树的代码实现:

TreeNode *buildTree(vector<int> &preorder, vector<int> &inorder)
{
        if(preorder.empty() && inorder.empty())
            return NULL;
        int root_val = preorder[0];//该子树根结点的元素值为先序遍历的第一个元素
        TreeNode* root = new TreeNode(root_val);//创建该子树的根结点
        vector<int> preorderL, preorderR, inorderL, inorderR;
        vector<int>::iterator it, it_a;//在中序遍历中查找根结点元素
        int i = 0;
        it = inorder.begin();
        while(*it != root_val)
        {
            it++;
            i++;
        }

        //确定中序遍历的左右子树序列
        for(it_a = inorder.begin(); it_a != it; it_a++)
            inorderL.push_back(*it_a);
        for(it_a = it+1; it_a != inorder.end(); it_a++)
            inorderR.push_back(*it_a);
        //确定前序遍历的左右子树序列
        it = preorder.begin();
        while(i)
        {
            it++;
            i--;
        }

        for(it_a = preorder.begin()+1; it_a != it+1; it_a++)
            preorderL.push_back(*it_a);
        for(it_a = it+1; it_a != preorder.end(); it_a++)
            preorderR.push_back(*it_a);

        //迭代构造二叉树
        root->left = buildTree(preorderL, inorderL);
        root->right = buildTree(preorderR, inorderR);

        return root;
}

这段代码在OJ里运行就报错了:Status:

Memory Limit Exceeded

。具体原因我现在也没搞明白……

思路二:用栈来实现。

1)用先序遍历序列中的第一个元素构造树的根结点,并将根结点指针入栈。

2)如果栈顶结点的元素值与中序遍历序列当前处理的元素值不相等,则一直用先序遍历序列中的元素构造树结点,如果flag标志值为0,将新结点添加为树当前处理结点的左孩子结点;否则,添加为右孩子结点。

3)如果栈顶结点的元素值与中序遍历序列当前处理的元素值相等,则将栈顶结点置为树的当前处理结点,然后将该结点出栈,并将flag标志置为1.

4)重复2)和3)的操作,直到先序遍历序列处理完。

用栈来实现构造二叉树的代码实现:

TreeNode *buildTree1(vector<int> &preorder, vector<int> &inorder)
{

    if(preorder.size()==0)
        return NULL;

    stack<TreeNode *> st;
    TreeNode *t, *root;
    int i, j;//i,j分别作为前序和中序遍历序列的处理指针
    int f;//用于标识是否要新建右结点

    f = i = j = 0;

    root = new TreeNode(preorder[i]);
    st.push(root);
    t = root;
    i++;

    while(i<preorder.size())
    {
        //case 1:栈顶结点的元素值与中序遍历当前值相等
        if(!st.empty() && st.top()->val == inorder[j])
        {
            t = st.top();
            st.pop();
            f = 1;
            j++;
        }
        else
        {
            //case 2a:f = 0,添加左结点
            if(f == 0)
            {
                t -> left = new TreeNode(preorder[i]);
                t = t -> left;
                st.push(t);
                i++;
            }
            //case 2b:f = 1,添加右结点
            else
            {
                f = 0;
                t -> right = new TreeNode(preorder[i]);
                t = t -> right;
                st.push(t);
                i++;
            }
        }
    }

    return root;
}

通过树的先序和中序遍历序列来构造二叉树

时间: 2024-07-31 21:18:51

通过树的先序和中序遍历序列来构造二叉树的相关文章

c++树,知道前序和中序求后序遍历

经常有面试题就是知道一棵树的前序遍历和中序遍历让你写出后序遍历,这个慢慢画是能画出来的,但是要很快的弄出来还是要懂原理. 首先说一下三种遍历:所谓的前序后序和中序都是遍历时遍历根节点的顺序.子树的话依照从做左到右的顺序,比如前序就是:中->左->右,中序就是:左->中->右. 现在前序是:ABDGCEFH 中序是:DGBAECHF 想要求后序就要把树重建出来,我们理一下思路. 1.由前序遍历的性质可以知道A必然是树的根节点 2.中序遍历中A之前的就肯定是A的左子树,A后面的就是A的

对树的一些操作.比如遍历.比如.根据先序和中序创建二叉树

1 #include "stdafx.h" 2 #include<string> 3 #include<iostream> 4 #include<stack> 5 6 using namespace std; 7 8 struct BinaryTreeNode 9 { 10 int m_nValue; 11 BinaryTreeNode* m_pLeft; 12 BinaryTreeNode* m_pRight; 13 }; 14 15 void b

树——二叉树的先序、中序和后序遍历

1,二叉树是否只有一种遍历方式(层次遍历)? 2,典型的二叉树的遍历方式: 1,先序遍历(Pre-Order Traversal): 2,中序遍历(In-Order Traversal): 3,后序遍历(Post-Order Traversal): 3,先序遍历(“先序”指最先访问根结点中的数据元素): 1,二叉树为空: 1,无操作,直接返回: 2,二叉树不为空: 1,访问根结点中的数据元素: 2,先序遍历左子树: 3,先序遍历右子树: 4,先序遍历功能定义及其代码实现: 1,代码示例: 1 p

二叉树高度,以及栈实现二叉树的先序,中序,后序遍历的非递归操作

求解二叉树的高度 树是递归定义的,所以用递归算法去求一棵二叉树的高度很方便. #include <iostream> #include <cstdio> using namespace std; struct Node { char data; Node *lchild; Node *rchild; }; void High(Node *T, int &h) { if (T == NULL) h = 0; else { int left_h; High(T->lchi

C语言非递归实现二叉树的先序、中序、后序、层序遍历

C语言非递归实现二叉树的先序.中序.后序.层序遍历代码如下: 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <stack> 4 #include <queue> 5 using namespace std; 6 7 //*****二叉树的二叉链表存储表示*****// 8 typedef struct BiNode 9 { 10 char data; 11 struct BiNode *lchil

如何由二叉树的先序和中序序列画出二叉树

今天数据结构的考试有这个题,做了好久,下来后,我好好地在网上查了一下,并结合我自己的理解,总结出来了一个比较好理解的方法.这个方法可以说做起这样的题又快又准. (概括为一个口诀:先序放中间,中序分两边)  基本思想就是递归:1.取出先序的第一个节点.(先序中的节点为根节点)2.用第一个节点可以将中序分成左右子树,然后又取出先序的第二个节点   再次将左右子树再次划分,3,当将中序全部划分为单个点时就结束.例如:假设一颗二叉树的先序序列是:EBADCFHGIKJ. 中序序列为:ABCDEFGHIJ

二叉树先序、中序、后序遍历的递归算法和非递归算法

先序遍历:若二叉树为空,则空操作:否则访问根节点:先序遍历左子树:先序遍历右子树. 中序遍历:若二叉树为空,则空操作:否则中序遍历左子树:访问根节点:中序遍历右子树. 后序遍历:若二叉树为空,则空操作:否则后序遍历左子树:后序遍历右子树:访问根节点. 二叉链表:链表中的结点包含三个域:数据域和左右指针域. 三叉链表:在二叉链表的基础上增加指向双亲结点的指针域. 以下代码均使用二叉链表. //二叉树的二叉链表存储表示 typedef char TElemType; typedef struct B

二叉树的先序、中序、后序遍历

二叉树的遍历方法有多种,首先我想先改变这几个遍历的名字(前根序遍历,中根序遍历,后根序遍历):前中后本来就是相对于根结点来说的,少一个字会产生很多不必要的误解. 先简单描述一下这三种遍历方法的区别: 先序遍历:先遍历根结点,然后遍历左子树,最后遍历右子树.上图中的先序遍历结果是ABDHECFG 中序遍历:先遍历左子树,然后遍历根结点,最后遍历右子树.上图中的中序遍历结果是HDBEAFCG 后序遍历:先遍历左子树,然后遍历右子树,最后遍历根节点.上图中的后序遍历结果是HDEBFGCA 先序遍历:

根据先序和中序实现后序

题目:已知先序和中序的数组,求输出后序输出结果.思路:根据先序和中序去建一棵二叉树然后后序遍历二叉树 #include<iostream> #include<string> #include<vector> #include<algorithm> using namespace std; struct node { int value; struct node* left; struct node* right; node(int _val) :value(