python實現統一形式的二叉樹前中後序非遞迴遍歷

2021-09-05 23:47:50 字數 4936 閱讀 7628

對於二叉樹的遍歷,遞迴形式非常簡單,可以很快寫出來,而對於非遞迴的形式,在不熟的情況下,還是需要一番思考的,因為二叉樹的非遞迴遍歷並沒有乙個統一的形式方便理解和記憶,對於前序和中序非遞迴遍歷,還算統一,而一般的非遞迴後序遍歷,和前兩者有很大的差異。

參考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.二叉查詢樹的最左邊的結點即為最小值,要查詢最小值,只需遍歷左子樹的結點直到為空為止,同理,最右邊的結點結尾最大值,要查詢最大值,只需遍歷右子樹的結點直到為空為止...