• LeetCode Binary Tree Inorder Traversal


    class Solution {
    public:
        vector<int> inorderTraversal(TreeNode *root) {
            vector<int> res;
            if (root == NULL) return res;
            vector<pair<TreeNode*, bool> > stack;
            stack.push_back(make_pair(root, false));
            
            while (!stack.empty()) {
                pair<TreeNode*, bool>& pn = stack.back();
                TreeNode* n = pn.first;
                if (pn.second) {
                    stack.pop_back();
                    res.push_back(n->val);
                    if (n->right != NULL) {
                        stack.push_back(make_pair(n->right, false));
                    }
                    continue;
                }
                pn.second = true;
                n = n->left;
                while (n != NULL) {
                    stack.push_back(make_pair(n, true));
                    n = n->left;
                }
            }
        }
        
        // a better one
        vector<int> _inorderTraversal(TreeNode *root) {
            vector<int> res;
            vector<TreeNode*> stack;
            
            while(root != NULL || !stack.empty()) {
                    while (root != NULL) {
                        stack.push_back(root);    
                        root=root->left;
                    }
                    if (!stack.empty()) {
                        root = stack.back();
                        stack.pop_back();
                        res.push_back(root->val); 
                        root = root->right;   
                    }
            }
        }
    };

    这种题想想简单,写起来也不好写,尤其是写的像第二个那么巧妙简洁,又找到一个比较通用的可以用在中序遍历和后续遍历中

    class Solution {
    public:
        vector<int> inorderTraversal(TreeNode *root) {
                    vector<int> res;
            if (root == NULL) return res;
            vector<pair<TreeNode*, bool> > stack;
            stack.push_back(make_pair(root, false));
            
            while (!stack.empty()) {
                pair<TreeNode*, bool>& pn = stack.back();
                TreeNode* n = pn.first;
                stack.pop_back();
                
                if (pn.second) {
                    res.push_back(n->val);
                } else {
                    if (n->right != NULL) {
                        stack.push_back(make_pair(n->right, false));
                    }
                    stack.push_back(make_pair(n, true));
                    if (n->left != NULL) {
                        stack.push_back(make_pair(n->left, false));    
                    }
                }
            }
            return res;
        }
    };

    不过以上花样百出,以前好几次都写过但又记不起来(当然能直接想出来的也就没必要看了),现在应该有个终极方法将这些问题统统秒杀掉,以防止其再来迫害人类。因为递归实质上是用到了栈,通过循环加上一个自己维护的栈也可以模拟递归的过程。除了保存在栈上的一般可编程变量外,在函数调用的时候会还会把下一条语句(指令)的CS:EIP存入栈中作为返回地址一般的递归函数返回后,会从调用位置的下一条语句(指令)再开始执行,这个学过汇编就应该非常明白。我们可以通过一个变量再结合switch语句简单而低效的实现这个过程,实质上是个状态机。下面来看代码

        vector<int> universal_traversal(TreeNode *root, int* map) {
            vector<int> res;
            vector<pair<TreeNode*, int> > stack;
            stack.push_back(make_pair(root, -1));
            while (!stack.empty()) {
                pair<TreeNode*, int>& np = stack.back();
                TreeNode* n = np.first;
                if (n == NULL) {
                    stack.pop_back();
                    continue;
                }
                np.second++;
                switch(map[np.second]) {
                    case 0: res.push_back(n->val);break;
                    case 1: stack.push_back(make_pair(n->left, -1));break;
                    case 2: stack.push_back(make_pair(n->right, -1));break;
                    default:stack.pop_back();
                }
            }
            return res;
        }
    
    void print(vector<int> nums) {
        for (int i=0; i<nums.size(); i++) {
            cout<<nums[i]<<" ";
        }
        cout<<endl;
    }
    
    int main() {
        TreeNode nodes[10];
        for (int i=0; i<10; i++) {
            nodes[i].val = i;
            nodes[i].left = NULL;
            nodes[i].right = NULL;
        }
        nodes[0].left = &nodes[1];
        // nodes[0].right= &nodes[2];
    
        nodes[1].right = &nodes[3];
        // nodes[1].right= &nodes[4];
        int preorder[] = {0, 1, 2, -1};
        int inorder[] =  {1, 0, 2, -1};
        int postorder[]= {1, 2, 0, -1};
        
        cout<<"Preorder: "<<endl;
        print(universal_traversal(&nodes[0], preorder));
        cout<<"Inorder: "<<endl;
        print(universal_traversal(&nodes[0], inorder));
        cout<<"Postorder: "<<endl;
        print(universal_traversal(&nodes[0], postorder));
        
        system("pause");
        return 0;
    }

     switch中的语句被函数中的map数组进行了映射,相当于几行代码重新排序了一下,因为树遍历重要的就三个语句(输出当前节点数据,左子树进栈,右子树进栈),通过不同的map数组映射,就分别得到了前序、中序、后序遍历的效果,从此妈妈再也不用担心我的学习!

    第二轮:

    Given a binary tree, return the inorder traversal of its nodes' values.

    For example:
    Given binary tree {1,#,2,3},

       1
        
         2
        /
       3
    

    return [1,3,2].

    Note: Recursive solution is trivial, could you do it iteratively?

    还是先用经典方法做吧:

     1 /**
     2  * Definition for binary tree
     3  * struct TreeNode {
     4  *     int val;
     5  *     TreeNode *left;
     6  *     TreeNode *right;
     7  *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
     8  * };
     9  */
    10 class Solution {
    11 public:
    12     vector<int> inorderTraversal(TreeNode *root) {
    13         vector<int> res;
    14         if (root == NULL) {
    15             return res;
    16         }
    17         
    18         vector<TreeNode*> stk;
    19         TreeNode* cur = root;
    20         while (cur != NULL) {
    21             while (cur != NULL) {
    22                 stk.push_back(cur);
    23                 cur = cur->left;
    24             }
    25             while (!stk.empty()) {
    26                 cur = stk.back();
    27                 res.push_back(cur->val);
    28                 stk.pop_back();
    29                 if (cur->right != NULL) {
    30                     break;
    31                 }
    32             }
    33 
    34             cur = cur->right;
    35         }
    36         return res;
    37     }
    38 };

     简洁一点:

    /**
     * Definition of TreeNode:
     * class TreeNode {
     * public:
     *     int val;
     *     TreeNode *left, *right;
     *     TreeNode(int val) {
     *         this->val = val;
     *         this->left = this->right = NULL;
     *     }
     * }
     */
    class Solution {
        /**
         * @param root: The root of binary tree.
         * @return: Inorder in vector which contains node values.
         */
    public:
        vector<int> inorderTraversal(TreeNode *root) {
            // write your code here
            vector<int> res;
            stack<TreeNode*> ns;
            TreeNode* curr = root;
            
            for (;;) {
                while (curr != NULL) {
                    ns.push(curr);
                    curr = curr->left;
                }
                if (ns.empty()) {
                    break;
                }
                TreeNode* tmp = ns.top();
                res.push_back(tmp->val);
                curr = tmp->right;
                ns.pop();
            }
            return res;
        }
    };
  • 相关阅读:
    MongoDB 基础
    类加载流程,类加载机制及自定义类加载器详解
    Object中有哪些方法及其作用
    Intellij IDEA 导入Maven项目
    用IDEA开发Spring程序
    深入浅出 Java 8 Lambda 表达式
    UUID.randomUUID()简单介绍
    json字符串转成 json对象 json对象转换成java对象
    字符串转 Boolean 的正确方式
    获取JSON中所有的KEY
  • 原文地址:https://www.cnblogs.com/lailailai/p/3615605.html
Copyright © 2020-2023  润新知