本篇波可完整** 請看二叉樹
先序非遞迴
我們先來回顧一下在什麼是先序遍歷;
先序遍歷二叉樹:
若二叉樹為空,則空操作;否則:
(1)訪問根結點;
(2)先序遍歷左子樹;
(3)先序遍歷右子樹;
這個在上次遞迴遍歷中已經說過了,所以我們就直接可以來進行非遞迴遍歷分析:
我們在考慮遞迴轉到非遞迴問題的時候,一定會用到乙個資料結構,它就是棧,為什麼是棧呢? 因為在棧的特性就是後進先出和遞迴的思路差不多,所以我們用棧這個資料結構來代替遞迴,就把問題轉化到非遞迴上面來:
我們先用看**然後來解釋為什麼這麼寫?
先序非遞迴**1:
void preorder_nor()
}
因為先序遍歷是根左右,棧是後進先出,所以在上面**中,先儲存了根結點,訪問完後就pop掉,然後儲存右結點在儲存左結點,棧頂先訪問的是左結點,就可以達到根左右的效果;
先序非遞迴**2:
void preorder_nor()
node* top = s.top();
s.pop();
pcur = top->_pright;}}
在上面的**中,我們可以看到是一上來就不管三七二十一先把他的左子樹的根結點全先訪問後入棧,然後在通過取棧頂元素來訪問他的右節點;
中序非遞迴
中序遍歷二叉樹:
若二叉樹為空,則空操作;否則:
(1)中序遍歷左子樹;
(2)訪問根結點;
(3)中序遍歷右子樹;
和先序遍歷一樣,我們還是要利用棧這個資料結構來把遞迴轉為非遞迴:
void inorder_nor()
node* top = s.top();
s.pop();
cout
<< top->_data << " ";
pcur = top->_pright;}}
在中序遍歷的時候是左根右來遍歷,所有我們在樹中先找到最左邊的葉子結點,從它開始訪問,所以上述的while迴圈中我們已經找到了最左邊的葉子結點,所以我們取棧頂元素就可以一步一步往回退著來訪問,其中最後一句中我們是不用管它的右子樹是否為空,因為在while(pcur)中可以判斷;
後序非遞迴
後序遍歷二叉樹:
若二叉樹為空,則空操作;否則:
(1)後序遍歷左子樹;
(2)後序遍歷右子樹;
(3)訪問根結點;
void postorder_nor()
node* top = s.top();
if (null == top->_pright || top->_pright == prve) //沒有後面這個條件可能造成對乙個有右節點的樹死迴圈訪問它的右子樹
else
pcur = top->_pright;}}
咋後序遍歷中,我們是左右根來遍歷的,所以我們還是利用棧來儲存結點,其中與其他不一樣的是,在後序遍歷中我們要yoga乙個指標來儲存上乙個結點,不然的還在注釋那一行如果樹的右子樹存在就會死迴圈,所以只要注意這一點,後序遍歷並不難;
二叉樹遍歷(遞迴 非遞迴)
二叉樹以及對二叉樹的三種遍歷 先根,中根,後根 的遞迴遍歷演算法實現,以及先根遍歷的非遞迴實現。node public class node public node left public node right public object value 遍歷訪問操作介面 public inte ce ...
二叉樹非遞迴遍歷
二叉樹非遞迴遍歷的幾個要點 1 不管前序 中序還是後序,它們的遍歷路線 或者說是回溯路線,先沿左邊一直走到盡頭,然後回溯到某節點,並跳轉到該節點的右孩子 如果有的話 然後又沿著這個有孩子的左邊一直走到盡頭 都是一樣的。2 明確每次回溯的目的。比如,前序回溯的目的是為了訪問右子樹 中序回溯的目的是為了...
非遞迴遍歷二叉樹
中序遞迴遍歷 void inordertrvdigui node pnode 然而,當樹的深度很大 比如16 時 假設為滿二叉樹 樹的節點數為 2 0 2 1 2 2 2 15 2 16 65536,遍歷整個二叉樹意味著有65536次函式呼叫,這將極大地增加程式執行時間。這時,應該採取非遞迴便利二叉...