學習筆記-二叉樹-先序、中序、後序、層次遍歷的實現(Python)
阿新 • • 發佈:2019-01-11
一、二叉樹類的Python實現及其函式:包括統計結點個數,用遞迴實現的先序遍歷,非遞迴實現的先序遍歷,以及非遞迴實現的後序遍歷。
class StackUnderflow(ValueError): pass class SStack(): def __init__(self): self.elems = [] def is_empty(self): return self.elems == [] def top(self): #取得棧裡最後壓入的元素,但不刪除 if self.elems == []: raise StackUnderflow('in SStack.top()') return self.elems[-1] def push(self, elem): self.elems.append(elem) def pop(self): if self.elems == []: raise StackUnderflow('in SStack.pop()') return self.elems.pop() class BinTNode: def __init__(self, dat, left = None, right = None): self.data = dat self.left = left self.right = right #統計樹中結點的個數 def count_BinTNodes(t): if t is None: return 0 else: return 1 + count_BinTNodes(t.left) + count_BinTNodes(t.right) #假設結點中儲存的是數值,求此時二叉樹裡的所有數值的和 def sum_BinTNodes(t): if t is None: return 0 else: return t.data + sum_BinTNodes(t.left) + sum_BinTNodes(t.right) def proc(x): print(x, end = '') #利用遞迴實現的先序遍歷 def pre_order(t): if t is None: return proc(t.data) pre_order(t.left) pre_order(t.right) #利用非遞迴實現的先序遍歷 def preorder_nonrec(t): s = SStack() while t is not None or not s.is_empty(): while t is not None: proc(t.data) s.push(t.right) #右分支入棧 t = t.left #沿著左分支下行 t = s.pop() #遇到空樹,回溯 #用帶有括號的形式顯示出樹,^代表空 def print_BinTNodes(t): if t is None: print('^', end = '') return print('(' + str(t.data), end = '') print_BinTNodes(t.left) print_BinTNodes(t.right) print(')', end = '') #用生成器實現非遞迴先序遍歷;當需要遍歷資料的時候,總應該想到迭代器 def preorder_elemnts(t): s = SStack() while t is not None or not s.is_empty(): while t is not None: s.push(t.right) #右分支入棧 yield t.data t = t.left t = s.pop() #非遞迴遍歷演算法的一個重要用途是作為實現迭代器的基礎 #利用非遞迴實現的後序遍歷 def postorder_elements(t): s = SStack() while t is not None or not s.is_empty(): while t is not None: #下行迴圈,知道到達樹的葉結點 s.push(t) #將樹壓入棧中 t = t.left if t.left is not None else t.right #如果左子結點不空就先訪問左子結點,為空就訪問右子結點 t = s.pop() #將棧頂的子樹彈出 proc(t.data) if not s.is_empty() and s.top().left == t: #如果棧不為空且當前的子樹是現在棧頂的左子結點 t = s.top().right #就轉到當前棧頂的右子結點 else: t = None if __name__=="__main__": t = BinTNode(1, BinTNode(2, BinTNode(4), BinTNode(5)), BinTNode(3, BinTNode(6), BinTNode(7))) t = BinTNode(1, BinTNode(2,BinTNode(5)), BinTNode(3)) print(count_BinTNodes(t)) print(sum_BinTNodes(t)) preorder_nonrec(t) print(pre_order(t)) print_BinTNodes(t) for i in preorder_elements(t): print(i) postorder_elements(t)
二、下面是不用自己構造的棧類所寫的4種遍歷的實現:
class BinTNode: def __init__(self, dat, left = None, right = None): self.data = dat self.left = left self.right = right # 利用遞迴實現的先序遍歷 def pre_order(t): if t == None: return print(t.data) pre_order(t.left) pre_order(t.right) # 利用遞迴實現的中序遍歷 def mid_order(t): if t == None: return mid_order(t.left) print(t.data) mid_order(t.right) # 利用遞迴實現的後序遍歷 def post_order(t): if t == None: return post_order(t.left) post_order(t.right) print(t.data) # 利用非遞迴實現的先序遍歷 def pre_order_nonrec(t): stack = [] while t != None or stack != []: while t != None: print(t.data) stack.append(t.right) # 右分支入棧 t = t.left # 沿著左分支下行 t = stack.pop() # 遇到空樹,回溯 # 利用非遞迴實現的中序遍歷 def mid_order_nonrec(t): stack = [] while t != None or stack != []: # 最開始時棧為空,但t不為空;t = t.right可能為空,棧不為空;當兩者都為空時,說明已經全部遍歷完成了 while t != None: stack.append(t) t = t.left t = stack.pop() # 將棧頂元素彈出 print(t.data) t = t.right # 將當前結點的右子結點賦給t,讓其在while中繼續壓入棧內 # 利用非遞迴實現的後序遍歷 def post_order_nonrec(t): stack = [] while t != None or stack != []: while t != None: # 下行迴圈,直到到達樹的葉結點 stack.append(t) # 將樹壓入棧中 t = t.left if t.left is not None else t.right # 如果左子結點不空就先訪問左子結點,為空就訪問右子結點 t = stack.pop() # 將棧頂的子樹彈出 print(t.data) if stack != [] and stack[-1].left == t: # 如果棧不為空且當前的子樹是現在棧頂的左子結點 t = stack[-1].right # 就轉到當前棧頂的右子結點 else: t = None #否則就直接置為None,從棧中彈出下一個元素 #層次遍歷 def level_order(t): if t == None: return lst = [] lst.append(t) while lst: current=lst.pop(0) print(current.data) if current.left!=None: lst.append(current.left) if current.right!=None: lst.append(current.right) if __name__ == "__main__": t = BinTNode(1, BinTNode(2, BinTNode(4), BinTNode(5)), BinTNode(3, BinTNode(6), BinTNode(7))) # t = BinTNode(1, BinTNode(2, BinTNode(5)), BinTNode(3)) pre_order(t) pre_order_nonrec(t) mid_order(t) mid_order_nonrec(t) post_order(t) post_order_nonrec(t) level_order(t)