顯然,我們需要用一個stack來模擬遞歸時的函數調用。對於三種遍歷,我們都使用push當前節點->push左子樹->pop左子樹->push右子樹->pop右子樹的方式。但是cout時機會有所不同。
對於前序遍歷來說,每次訪問到一個節點就cout;
對於中序遍歷來說,每次將右子節點進棧時,把當前節點cout;
對於後序遍歷來說,每次pop的時候cout。
另外我們還需要一個last_pop指針來存放上一個pop出去的節點。
如果當前節點的左右節點都不是上一個pop的節點,那麼我們將左子節點入棧;
如果當前節點的左節點是上一個pop的節點,但右節點不是,那麼就把右子節點入棧;
否則的話,就需要讓當前節點出棧。
大致思路就是這樣,俗話說Talk is cheap, let's coding. 直接上代碼,注意三種遍歷的代碼總體結構都是完全一樣的,只是cout的時機有所不同。
前序遍歷的非遞歸版本
void preorder_traversal_iteratively(TreeNode* root)
{
if (root == 0)
return;
stack<TreeNode*> s;
s.push(root);
cout << root->val << ' '; // visit root
TreeNode* last_pop = root;
while (!s.empty())
{
TreeNode* top = s.top();
if (top->left != NULL && top->left != last_pop && top->right != last_pop) // push_left
{
s.push(top->left);
cout << top->left->val << ' '; // visit top->left
}
else if (top->right != NULL && top->right != last_pop && (top->left == 0 || top->left == last_pop)) // push_right
{
s.push(top->right);
cout << top->right->val << ' '; // visit top->right
}
else // pop
{
s.pop();
last_pop = top;
}
}
}
中序遍歷的非遞歸版本void inorder_traversal_iteratively(TreeNode* root)
{
if (root == 0)
return;
stack<TreeNode*> s;
s.push(root);
TreeNode* last_pop = root;
while (!s.empty())
{
TreeNode* top = s.top();
if (top->left != 0 && top->left != last_pop && top->right != last_pop) // push_left
{
s.push(top->left);
}
else if (top->right != 0 && top->right != last_pop && (top->left == 0 || top->left == last_pop)) // push_right
{
s.push(top->right);
cout << top->val << ' '; // visit top
}
else // pop
{
s.pop();
last_pop = top;
if (top->right == 0)
cout << top->val << ' '; // visit top
}
}
}
後序遍歷的非遞歸版本
void postorder_traversal_iteratively(TreeNode* root)
{
if (root == 0)
return;
stack<TreeNode*> s;
s.push(root);
TreeNode* last_pop = root;
while (!s.empty())
{
TreeNode* top = s.top();
if (top->left != 0 && top->left != last_pop && top->right != last_pop) // push_left
{
s.push(top->left);
}
else if (top->right != 0 && top->right != last_pop && (top->left == 0 || top->left == last_pop)) // push_right
{
s.push(top->right);
}
else // pop
{
s.pop();
last_pop = top;
cout << top->val << ' '; // visit top
}
}
}