首先。先序遍历是先访问根节点。然后左节点 然后右节点。从根节点开始 直到它的子节点没有左节点才开始回溯访问上一个节点的右节点。同理。中序遍历 先访问左节点 然后是父节点 然后是右节点。从根节点开始 直到它的孩子节点没有左节点 才开始回溯访问该节点 然后是它的父节点 然后是它的兄弟右节点。也就是说 每次访问一个节点时 它的左节点已经被访问过了。访问过之后 就要访问它的 右节点。(有点醉T_T.......)后续遍历。从根节点开始 直到叶子节点。先访问左节点 然后是右节点。然后回溯访问父节点。注意回溯到总的根节点时不能直接访问 还要像左子树一样遍历到叶子节点访问完左右节点时才能访问该节点。也就是说。每次访问一个节点 都要确定它的左右节点都已经被访问完。。。。。。。赤果果的深搜啊。。。。。。。。

额....这个题是给你先序和中序求后序。也可以根据后序和中序写出前序。但是不可能根据前序和后序求中序...(然而我并不懂为什么.........)

明白了这些....这就是dfs了...注意好好理解前序确定父节点的信息....中序确定左右子树的元素....于是唯一确定了后序数列....附代码:

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<stack>
using namespace std;

int pre[1010], in[1010];
stack<int>aft;  //存放父节点。即后续遍历数列。

void build(int l1, int r1, int l2, int r2)  // l1,r1表示前序遍历数组的开始和结尾。 l2和r2表示中序遍历数组的开始和结尾。
{
     int i;
     aft.push(pre[l1]); // 父节点入栈
     for (i=l2; i<=r2; ++i)
     {
         if (pre[l1] == in[i])
            break;  //找到父节点在中序遍历数组里的位置。
     }
     int j = l1+(i-l2+1); //找到右子树的父节点在先序数组里的位置。即左子树和右子树在先序遍历的分界点
     if (j<=r1 && i+1<=r2)  // 该节点在中序遍历数组里右边还有数即存在右子树,且右子树父节点在先序范围里
     {
         build(j, r1, i+1, r2); // 求解右子树.因为要求的是后续遍历数列而且存储在栈中。所以每次先找右子树。再找左子树。
     }
     if (l1+1<=j-1 && l2<=i-1)
     {
         build(l1+1, j-1, l2, i-1);  // 求解左子树。
     }
}

int main()
{
    int n;
    while (cin >> n)
    {
        for (int i=0; i<n; ++i)
        {
            cin >> pre[i];
        }
        for (int i=0; i<n; ++i)
        {
            cin >> in[i];
        }
        build(0, n-1, 0, n-1);
        bool flag = true;
        while(!aft.empty())
        {
            if (flag)
            {
                cout << aft.top();
                flag = false;
            }
            else
            {
               cout << ' ' << aft.top();
            }
            aft.pop();
        }
        cout << endl;
    }
    return 0;
}

posted on 2015-07-24 10:18  小小八  阅读(575)  评论(0编辑  收藏  举报