手写递归栈

 1 void preorderTraversalNew(TreeNode *root, vector<int> &path) {
 2     stack< pair<TreeNode *, bool> > s;
 3     s.push({root, false});
 4     bool visited;
 5     while(!s.empty()) {
 6         root = s.top().first;
 7         visited = s.top().second;
 8         s.pop();
 9         if(root == NULL) continue;
10         if(visited) path.push_back(root->val);
11         else {
12             s.push({root->right, false});
13             s.push({root->left, false});
14             s.push({root, true});    //改变这句的位置, 可达到先序, 中序, 后序效果, true表示已对该节点展开其子节点
15         }
16     }
17 }

 以上以二叉树的非递归先序遍历为例。

其他dfs递归也可以类似这么写,以<int NodeID, bool visit>的形式压入栈中。

注意将子节点压栈的时候顺序会改变,要保持与dfs同序,应当将子节点从右往左压栈。

===================================================================================================

Morris Traversal算法

O(1)空间复杂度, O(n)时间复杂度,允许修改原始二叉树数据。

先序遍历二叉树转链表(存于右儿子指针域):leetcode114. Flatten Binary Tree to Linked List

class Solution {
public:
    void flatten(TreeNode *root) {
        TreeNode*now = root;
        while (now) {
            if(now->left) {
                TreeNode* pre = now->left;
                while(pre->right)
                    pre = pre->right;
                pre->right = now->right;
                now->right = now->left;
                now->left = NULL;
            }
            now = now->right;
        }
    }
};

http://www.cnblogs.com/AnnieKim/archive/2013/06/15/MorrisTraversal.html

https://stackoverflow.com/questions/6478063/how-is-the-time-complexity-of-morris-traversal-on

===================================================================================================

其它做法

可以给每个节点添加两个额外的域,cur表示已经遍历了几条出边,f表示父节点,

即vector<int> G[N], cnt[N].

G[i]存i的出边所到的点,cnt存当前遍历到第cnt个点。

dfs的时候可以尾递归优化。

也可以写成迭代式。

原文地址:https://www.cnblogs.com/dirge/p/8651047.html