二叉树的遍历

先序遍历(迭代版)

自上而下对左侧分支访问的同时将右子树根节点入栈,自下而上对右子树遍历。


class Solution {
     
public:
    stack<TreeNode*> stk;
    vector<int> pre;

    void travelLeft(TreeNode* x){
     
        while(x){
     
            stk.push(x->right);
            pre.push_back(x->val);
            x = x->left;
        }
    }

    vector<int> preorderTraversal(TreeNode* root) {
     
        if(!root) return pre;
        stk.push(root);
        while(stk.size()){
     
            auto t = stk.top(); stk.pop();
            travelLeft(t);
        }
        return pre;
    }
};

中序遍历(迭代版)

自上而下一路向左遍历找到该树最左侧的节点,并用栈记录下最左侧的节点的祖先,访问完最左节点后开始遍历右子树。

class Solution {
     
public:
    vector<int> in;
    stack<TreeNode*> stk;

    void traverLeft(TreeNode* x){
     
        while(x){
     
            stk.push(x);
            x = x->left;
        }
    }

    vector<int> inorderTraversal(TreeNode* root) {
     
        TreeNode* p = root;
        while(true){
     
            traverLeft(p);
            if(stk.empty()) return in;
            p = stk.top(); stk.pop();
            in.push_back(p->val);
            p = p->right;
        }
        return in;
    }
};

后序遍历(迭代版)

找到第一个被访问的节点,并用栈记录下沿途经过的节点以及它们的右孩子。访问结束后,依次访问右孩子。

class Solution {
     
public:
    stack<TreeNode*> stk;
    vector<int> post;

    void gotoFirst(){
     
        while(auto p = stk.top()){
     
            //一路向左
            if(p->left){
     
                //右孩子后入栈
                if(p->right) stk.push(p->right);
                stk.push(p->left);
            }
            //没有左孩子时转向右
            else stk.push(p->right);
        }
        //弹出空指针
        stk.pop();
    }

    vector<int> postorderTraversal(TreeNode* root) {
     
        if(!root) return post;
        TreeNode* p = root;
        stk.push(root);
        while(!stk.empty()){
     
            //如果栈顶节点不是上一个遍历过的节点的父亲
            //则栈顶节点必然是p的右兄弟
            if(stk.top()->left != p && stk.top()->right != p)
                gotoFirst();
            p = stk.top(); stk.pop();
            post.push_back(p->val); 
        }
        return post;
    }
};

前序和中序构造二叉树

class Solution {
     
public:
    vector<int> pre, in;
    unordered_map<int, int> pos;

    TreeNode* dfs(int pl, int pr, int il, int ir) {
     
        int r = pre[pl], k = pos[r];
        auto root = new TreeNode(r);
        if(il <= k-1) root->left = dfs(pl+1, pl+1+k-1-il, il, k-1);
        if(k+1 <= ir) root->right = dfs(pl+k-il+1, pr, k+1, ir);
        return root;
    }

    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
     
        if(preorder.empty() || inorder.empty()) return NULL;
        pre = preorder, in = inorder;
        for(int i = 0; i < in.size(); i ++)
            pos[in[i]] = i;
        return dfs(0, pre.size()-1, 0, in.size()-1);
    }
};

后序和中序构造二叉树

class Solution {
     
public:
    unordered_map<int, int> pos;
    vector<int> post;

    TreeNode* dfs(int il, int ir, int pl, int pr){
     
        int r = post[pr], k = pos[r];
        auto root = new TreeNode(r);
        if(k-1 >= il) root->left = dfs(il, k-1, pl, pl+k-1-il);
        if(k+1 <= ir) root->right = dfs(k+1, ir, pl+k-il, pr-1);
        return root;
    }

    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
     
        if(inorder.empty() || postorder.empty()) return NULL;
        post = postorder;
        int n = inorder.size();
        for(int i = 0; i < n; i ++)
            pos[inorder[i]] = i;
        return dfs(0, n-1, 0, n-1);
    }
};

前序和后序遍历构造二叉树(不唯一)

前序序列和后序序列无法完全确定一颗二叉树,除非这是一棵真二叉树(每个节点的度数只能是2或0)。

class Solution {
     
public:
    unordered_map<int, int> pos;
    vector<int> pre, post; 

    TreeNode* dfs(int l1, int r1, int l2, int r2){
     
        if(l2 > r2) return NULL;
        auto root = new TreeNode(post[r2]);
        if(l2 == r2) return root;
        int k = pos[pre[l1+1]];
        root->left = dfs(l1+1, l1+1+k-l2, l2, k);
        root->right = dfs(l1+2+k-l2, r1, k+1, r2-1);
        return root;
    }

    TreeNode* constructFromPrePost(vector<int>& _pre, vector<int>& _post) {
     
        if(_pre.empty() || _post.empty()) return NULL;
        pre = _pre, post = _post;
        int n = post.size();
        for(int i = 0; i < n; i ++)
            pos[post[i]] = i;
        
        return dfs(0, n-1, 0, n-1);
    }
};

前序和后序遍历(可算出可能的二叉树数量)

#include 
using namespace std;

const int N = 35;
int pre[N], post[N];

int dfs(int l1, int r1, int l2, int r2, string& in){
     
    if(l1 > r1) return 1;
    if(pre[l1] != post[r2]) return 0;
    
    int cnt = 0;
    for(int i = l1; i <= r1; i ++){
     
        string lin, rin;
        int lcnt = dfs(l1+1, i, l2, l2+i-l1-1, lin);
        int rcnt = dfs(i+1, r1, l2+i-l1, r2-1, rin);
        if(lcnt && rcnt){
     
            in = lin + to_string(pre[l1]) + " " + rin;
            cnt += lcnt*rcnt;
        }
        
        if(cnt > 1) break;
    }
    return cnt;
}

int main(){
     
    int n;
    cin >> n;
    for(int i = 0; i < n; i ++){
     
        scanf("%d", &pre[i]);
    }
    for(int i = 0; i < n; i ++){
     
        scanf("%d", &post[i]);
    }
    
    string in;
    int cnt = dfs(0, n-1, 0, n-1, in);
    in.pop_back();
    
    if(cnt == 1) puts("Yes");
    else puts("No");
    
    cout << in <<  endl;
}

你可能感兴趣的:(二叉树,dfs)