在網上看了一些用非遞迴實現先序中序後序遍歷二叉樹的**,都很混亂,while、if各種組合巢狀使用,邏輯十分不清晰,把我也搞懵了。想了大半天,寫了大半天,突然開了竅,實際上二叉樹的這三種遍歷在邏輯上是十分清晰的,所以才可以用遞迴實現的那麼簡潔。既然邏輯如此清晰,那麼用非遞迴實現也應該是清晰的。
自認為自己的**比網上搜到的那些都清晰得多,好理解得多。
稍微解釋一下:
先序遍歷。將根節點入棧,考察當前節點(即棧頂節點),先訪問當前節點,然後將其出棧(已經訪問過,不再需要保留),然後先將其右孩子入棧,再將其左孩子入棧(這個順序是為了讓左孩子位於右孩子上面,以便左孩子的訪問先於右孩子;當然如果某個孩子為空,就不用入棧了)。如果棧非空就重複上述過程直到棧空為止,結束演算法。
中序遍歷。將根節點入棧,考察當前節點(即棧頂節點),如果其左孩子未被訪問過(有標記),則將其左孩子入棧,否則訪問當前節點並將其出棧,再將右孩子入棧。如果棧非空就重複上述過程直到棧空為止,結束演算法。
後序遍歷。將根節點入棧,考察當前節點(即棧頂節點),如果其左孩子未被訪問過,則將其左孩子入棧,否則如果其右孩子未被訪問過,則將其右孩子入棧,如果都已經訪問過,則訪問其自身,並將其出棧。如果棧非空就重複上述過程直到棧空為止,結束演算法。
其實,這只不過是保證了先序中序後序三種遍歷的定義。對於先序,保證任意乙個節點先於其左右孩子被訪問,還要保證其左孩子先於右孩子被訪問。對於中序,保證任意乙個節點,其左孩子先於它被訪問,右孩子晚於它被訪問。對於後序,保證任意乙個節點的左孩子右孩子都先於它被訪問,其中左孩子先於右孩子被訪問。如是而已。
**裡應該體現得比較清楚。這裡不光給出了非遞迴版本,也給出了遞迴版本。
[cpp]view plain
copy
#include
#include
using
namespace
std;
struct
treenode
; typedef
treenode *treeptr;
treeptr createtree()
else
return
root;
} void
preorderrecursion(treeptr p)
cout; preorderrecursion(p->left);
preorderrecursion(p->right);
} void
inorderrecursion(treeptr p)
inorderrecursion(p->left);
cout; inorderrecursion(p->right);
} void
postorderrecursion(treeptr p)
postorderrecursion(p->left);
postorderrecursion(p->right);
cout; }
void
preordernorecursion(treeptr p)
if(t.left != null)
} } void
inordernorecursion(treeptr p)
} else
} } }
void
postordernorecursion(treeptr p)
}
else
if(stk.top().flag == 1)
}
else
} } int
main()
二叉樹的非遞迴遍歷(先序,中序,後序)
遍歷演算法 1 中序遍歷的遞迴演算法定義 若二叉樹非空,則依次執行如下操作 1 遍歷左子樹 2 訪問根結點 3 遍歷右子樹。2 先序遍歷的遞迴演算法定義 若二叉樹非空,則依次執行如下操作 1 訪問根結點 2 遍歷左子樹 3 遍歷右子樹。3 後序遍歷得遞迴演算法定義 若二叉樹非空,則依次執行如下操作 ...
二叉樹的非遞迴先序,中序,後序遍歷
二叉樹的非遞迴遍歷 先序遍歷,中序遍歷,後序遍歷 include include using namespace std typedef struct node binode,bitree 先序遞迴建立樹,這裡注意引數的型別,t的型別是 如果是 稍加改動就ok.void createtree bit...
二叉樹的非遞迴先序 中序 後序遍歷
演算法思想 先序 nlr的訪問順序,由於r節點,即右孩子的訪問需要通過根節點的指標來實現,所以,需要設乙個棧來儲存根節點。具體看 void preorder btree t else while 中序遍歷和先序遍歷幾乎一樣 void midorder btree t else 後序遍歷 lrn順序。...