用python實現二叉搜尋樹/查詢樹的簡單實現及驗證(判斷)(三)(棧中根序遍歷)
基於棧的中根序深度優先遍歷判斷法(天然排序,每次比上一個值大即可)。
由搜尋樹的性質推得中根序深度遍歷為一個從小到大的有序序列。所以根據這一性質事情就好辦了,只要在遍歷過程中加入與前一值得比較判斷即能達到目的(複雜度O(n),推薦演算法)。程式碼如下:
def midorder(t): #中根序遍歷比較判斷,複雜度O(n)推薦演算法
s = [] #工作棧,為省事直接用list沒有從新定義一個棧類再用
a = [] #一個表記錄已經遍歷過的結點以便回溯時不再次遍歷
b = float('-Inf') #用於記錄上一單位遍歷的值,初始化為負無窮
while t or len(s): #t不為None或棧不空
if ((not t.right)and(not t.left))or t in a: #無子節點或已遍歷過
if t.data <= b: #比較判斷
return False
else:
b = t.data
if len(s):
t = s.pop() #彈出下一個
else:
return True #棧空,執行完沒False則返回True
continue #再從迴圈體頭部開始執行
else: #有子節點且沒遍歷過,依次將右子,中,左子入棧
if t.right:
s.append(t.right)
s.append(t)
if t.left:
s.append(t.left)
a.append(t) #記錄此節點已遍歷過
t = s.pop() #彈出下一個
這個是O(n)(約4n,中根序遍歷3n)複雜度的演算法,已測過可用。其它幾篇思路可行,但有的複雜度不是最優,所以只寫出來記錄下。不放心的也可以再測下:
class Node(object):
def __init__(self,data,left=0,right=0):
self.data=data
self.left=left
self.right=right
if __name__ == '__main__':
# 手動建立一課二叉樹
tree = Node(1)
tree.left = Node(2, None, None)
tree.right = Node(3, None, None)
tree.left.left = Node(4, None, None)
tree.left.right = Node(5, None, None)
tree.right.left = Node(6, None, None)
tree.right.right = Node(7, None, None)
tree.left.left.left = Node(8, None, None)
tree.left.left.right = Node(9, None, None)
tree.left.right.left = Node(10, None, None)
tree.left.right.left.right = Node(11, None, None)
print("手動建立一個二叉樹(非搜尋樹)並判斷")
print(midorder(tree))
#再建立一個搜尋樹
print("再建立一個二叉樹(搜尋樹)並判斷")
tree0 = Node(8)
tree0.left = Node(5, None, None)
tree0.right = Node(10, None, None)
tree0.left.left = Node(3, None, None)
tree0.left.right = Node(6, None, None)
tree0.right.left = Node(9, None, None)
tree0.right.right = Node(11, None, None)
tree0.left.left.left = Node(2, None, None)
tree0.left.left.right = Node(4, None, None)
print(midorder(tree0))
————全文完,歡迎轉載,但請註明出處!