對於二叉樹的遍歷,遞迴形式非常簡單,可以很快寫出來,而對於非遞迴的形式,在不熟的情況下,還是需要一番思考的,因為二叉樹的非遞迴遍歷並沒有乙個統一的形式方便理解和記憶,對於前序和中序非遞迴遍歷,還算統一,而一般的非遞迴後序遍歷,和前兩者有很大的差異。
參考python實現二叉樹和它的七種遍歷,給出一般形式的非遞迴前中後序遍歷:
一般形式的非遞迴前中後序遍歷
def
front_stack
(self, root)
:"""利用堆疊實現樹的先序遍歷"""
if root ==
none
:return
mystack =
node = root
while node or mystack:
while node:
#從根節點開始,一直找它的左子樹
print
(node.elem)
node = node.lchild
node = mystack.pop(
)#while結束表示當前節點node為空
node = node.rchild #開始檢視它的右子樹
defmiddle_stack
(self, root)
:"""利用堆疊實現樹的中序遍歷"""
mystack =
node = root
while node or mystack:
while node:
#從根節點開始,一直找它的左子樹
node = node.lchild
node = mystack.pop(
)#while結束表示當前節點node為空
print
(node.elem)
node = node.rchild #開始檢視它的右子樹
deflater_stack
(self, root)
:"""利用堆疊實現樹的後序遍歷"""
if root ==
none
:return
mystack1 =
mystack2 =
node = root
while mystack1:
#這個while迴圈的功能是找出後序遍歷的逆序,存在mystack2裡面
node = mystack1.pop(
)if node.lchild:
if node.rchild:
while mystack2:
#將mystack2中的元素出棧,即為後序遍歷次序
print
(mystack2.pop(
).elem)
非遞迴後序遍歷不同的原因
從**中可以看出,前中序非遞迴遍歷較為相似,只有節點訪問的位置不一樣,但也有差別,前者是在入棧前訪問,後者是出棧後訪問。
而後序遍歷就大不一樣了,它不能和上面的前中序一樣,是因為它需要訪問完右子樹之後才訪問當前節點,而在上面前序和中序裡的棧,在訪問右子樹之前已經把當前節點pop出去了,不可能再訪問到當前節點,因此不能簡單像下面的遞迴版本一樣把節點訪問放在最後就可以了。
def
later_recursive
(self, root)
:"""利用遞迴實現樹的後序遍歷"""
if root ==
none
:return
self.later_digui(root.lchild)
self.later_digui(root.rchild)
print
(root.elem)
上面的遞迴後序遍歷中,因為在當前訪問節點下,root一直被儲存,不受訪問左右子樹的影響,因此,當前節點的訪問直接放在最後即可。
統一形式的非遞迴前中後序遍歷
下面給出一種統一形式的二叉樹非遞迴遍歷,它和遞迴版的一樣,只要更改一行**的位置即可。
但它的時間複雜度相較上面的方法會更高一些,因為它需要對節點進行兩次遍歷,第一次並不訪問,第二次再訪問,因此需要乙個記錄訪問次數的flag,在空間複雜度上也會更大,但它統一的形式能更好的理解。
class
node
(object):
"""節點類"""
def__init__
(self, elem=-1
, lchild=
none
, rchild=
none):
self.elem = elem
self.lchild = lchild
self.rchild = rchild
class
tree
(object):
"""樹類"""
def__init__
(self)
: self.root = node(
) self.myqueue =
defadd
(self, elem)
:"""為樹新增節點,生成完全二叉樹"""
node = node(elem)
if self.root.elem ==-1
:# 如果樹是空的,則對根節點賦值
self.root = node
else
: treenode = self.myqueue[0]
# 此結點的子樹還沒有齊。
if treenode.lchild ==
none
: treenode.lchild = node
else
: treenode.rchild = node
self.myqueue.pop(0)
# 如果該結點存在右子樹,將此結點丟棄。
deffront_recursive
(self, root)
:"""利用遞迴實現樹的先序遍歷"""
if root ==
none
:return
print
(root.elem)
self.front_recursive(root.lchild)
self.front_recursive(root.rchild)
defmiddle_recursive
(self, root)
:"""利用遞迴實現樹的中序遍歷"""
if root ==
none
:return
self.middle_recursive(root.lchild)
print
(root.elem)
self.middle_recursive(root.rchild)
deflater_recursive
(self, root)
:"""利用遞迴實現樹的後序遍歷"""
if root ==
none
:return
self.later_recursive(root.lchild)
self.later_recursive(root.rchild)
print
(root.elem)
deffront_loop
(self,root)
:"""利用迴圈實現樹的前序遍歷"""
stack =
(root,0)
)while stack:
node, isvisit = stack.pop()if
not node:
continue
if isvisit:
print
(node.elem)
else
:(node.rchild,0)
)(node.lchild,0)
)(node,1)
)def
middel_loop
(self,root)
:"""利用迴圈實現樹的中序遍歷"""
stack =
(root,0)
)while stack:
node, isvisit = stack.pop()if
not node:
continue
if isvisit:
print
(node.elem)
else
:(node.rchild,0)
)(node,1)
)(node.lchild,0)
)def
later_loop
(self,root)
:"""利用迴圈實現樹的後序遍歷"""
stack =
(root,0)
)while stack:
node, isvisit = stack.pop()if
not node:
continue
if isvisit:
print
(node.elem)
else
:(node,1)
)(node.rchild,0)
)(node.lchild,0)
)if __name__ ==
'__main__'
:"""主函式"""
elems =
range(10
)#生成十個資料作為樹節點
tree = tree(
)#新建乙個樹物件
for elem in elems:
tree.add(elem)
#逐個新增樹的節點, 生成完全二叉樹
tree.front_recursive(tree.root)
tree.front_loop(tree.root)
參考:更簡單的非遞迴遍歷二叉樹的方法 Python實現二叉搜尋
二叉搜尋是在乙個有序的列表中,尋找目標元素。因此我們需要對半查詢即可。當目標元素比中間元素小,則在中間元素的左邊查詢 反之,則在目標元素的右邊查詢。直到左邊界比右邊界還要大停止查詢。def binarysearch target,arr right len arr 1 left 0 while le...
二叉搜尋樹的python實現
二叉搜尋樹,特點是左節點的值小於根節點的值,右節點的值大於根節點的值,並且左右子樹也遵循這個規律.class binarysearchtree object def init self,key self.key key self.left none self.right none deffind s...
二叉查詢樹python實現
1.二叉查詢樹的定義 左子樹不為空的時候,左子樹的結點值小於根節點,右子樹不為空時,右子樹的結點值大於根節點,左右子樹分別為二叉查詢樹 2.二叉查詢樹的最左邊的結點即為最小值,要查詢最小值,只需遍歷左子樹的結點直到為空為止,同理,最右邊的結點結尾最大值,要查詢最大值,只需遍歷右子樹的結點直到為空為止...