手写递归栈
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的时候可以尾递归优化。
也可以写成迭代式。
诸神对凡人心生艳羡,厌倦天堂。