1. 程式人生 > >二叉樹非遞歸遍歷

二叉樹非遞歸遍歷

post 出棧 log left vector 規則 preorder void highlight

一、非遞歸先序遍歷:先遍歷根節點,後左,再右。先訪問即任一節點,其可看作是根節點,因此可以直接訪問;訪問之後,若其左孩子不為空,按相同的規則訪問他的左子樹。

當訪問其左子樹,再訪問其右子樹,處理過程如下:

1、訪問節點cur,將其入棧;

2、判斷節點cur的左孩子是否為空,若為空,則取棧頂節點出棧,並將其右孩子置為當前訪問節點。

3、若不為空,則循環將其左孩子置為當前節點。

註意:訪問結點的位置要在循環中,先訪問。

 1 void PreOrder(TreeNode* root,vector<int>& res)
 2 {
 3     stack<TreeNode*> s;
4 TreeNode* cur=root; 5 while (!s.empty() || cur) 6 { 7 while (cur) 8 { 9 res.push_back(cur->val); 10 s.push(cur); 11 cur = cur->left; 12 } 13 if (!s.empty()) 14 { 15 cur = s.top(); 16 s.pop();
17 cur = cur->right; 18 } 19 } 20 21 }

2、非遞歸中序遍歷:根據中序遍歷的要求,優先訪問其左孩子,而左孩子節點又可以看作是一根節點,然後繼續訪問其左孩子,直到遇到左孩子節點為空才進行訪問,然後按相同規則訪問右子樹。

對於節點cur ,若其左孩子不為空,則將cur入棧,並將其左孩子置為當前cur.然後當前cur做出相同處理。

若其左孩子為空,則取棧頂元素並進行出棧,訪問該棧頂元素,然後將當前cur的右孩子置為cur.

註意:主要是訪問節點的時機同先序不同

void InOrder(TreeNode* root,vector<int>& res)
{
	stack<TreeNode*> s;
	TreeNode* cur=root;
	while (!s.empty() || cur)
	{
		while (cur)
		{
			s.push(cur);
			cur = cur->left;
		}
		if (!s.empty())
		{
			cur = s.top();
			res.push_back(cur->val);//先訪問左孩子。不是在入棧過程中訪問了
			s.pop();
			cur = cur->right;
		}
	}

}

  

3、非遞歸後序遍歷:後序遍歷中要保證左孩子和右孩子都已經被訪問過並且左孩子在右孩子之前訪問才能訪問根節點。

要保證根節點在左右子樹訪問之後才能訪問因此對於任意節點cur,先將其入棧。

1、如果cur不存在左孩子和右孩子則直接訪問。

2、如果cur存在左孩子或者右孩子,但是左孩子或右孩子都已經被訪問過了。

同樣可以訪問該節點,所以可以引入一個pre節點,存儲前一次訪問的節點。

如果不是上面的兩種情況,則將cur的右孩子入棧

再將cur的左孩子入棧(一定要現將右孩子入棧)

 1 void PostOrder(TreeNode* root,vector<int>& res)
 2 {
 3     stack<TreeNode*> s;
 4     TreeNode* cur;
 5     TreeNode* pre = NULL;
 6     if (!root)  return;
 7     s.push(root);
 8     while (!s.empty())
 9     {
10         cur = s.top();
11         if (!cur->left&&!cur->right||(pre!==NULL&&(pre==cur->left||pre==cur->right)))
12         {
13             res.push_back(cur->val);
14             s.pop();
15             pre = cur;
16         }
17         else
18         {
19             if (cur->right)  s.push(cur->right);
20             if (cur->left)  s.push(cur->left);
21         }
22     }
23 
24 }

二叉樹非遞歸遍歷