樹(英語:tree)是一種抽象數據類型(ADT)或是實做這種抽象數據類型的數據結構,用來模擬具備樹狀結構性質的數據集合。它是由n(n>=1)個有限節點組成一個具備層次關係的集合。把它叫作「樹」是由於它看起來像一棵倒掛的樹,也就是說它是根朝上,而葉朝下的。它具備如下的特色:html
圖示:node
將數據結構存儲在固定的數組中,雖然在遍歷速度上有必定的優點,但因所佔空間比較大,是非主流二叉樹。二叉樹一般以鏈式存儲。mysql
因爲對節點的個數沒法掌握,常見樹的存儲表示都轉換成二叉樹進行處理,子節點個數最多爲2。算法
二叉樹是每一個節點最多有兩個子樹的樹結構。一般子樹被稱做「左子樹」(left subtree)和「右子樹」(right subtree)。sql
若設二叉樹的高度爲h,除第 h 層外,其它各層 (1~h-1) 的結點數都達到最大個數,第h層有葉子結點,而且葉子結點都是從左到右依次排布,這就是徹底二叉樹。數據庫
除了葉結點外每個結點都有左右子葉且葉子結點都處在最底層的二叉樹。數組
1 class Node: 2 """樹的節點類""" 3 def __init__(self, item): 4 self.elem = item 5 self.lchild = None 6 self.rchild = None 7 8 9 class Tree: 10 """二叉樹""" 11 12 def __init__(self, root=None): 13 """初始化根節點""" 14 self.root = root 15 16 def add(self, elem): 17 """爲樹添加節點""" 18 node = Node(elem) 19 # 若是樹是空的,則爲根節點賦值 20 if self.root is None: 21 self.root = node 22 else: 23 queue = [] 24 queue.append(self.root) 25 # 對已有節點進行層次遍歷 26 while queue: 27 # 彈出隊列的第一個元素(先進先出) 28 cur_node = queue.pop(0) 29 if cur_node.lchild is None: 30 cur_node.lchild = node 31 return 32 elif cur_node.rchild is None: 33 cur_node.rchild = node 34 return 35 # 若是左右子樹都不爲空,加入隊列繼續判斷 36 else: 37 queue.append(cur_node.lchild) 38 queue.append(cur_node.rchild)
樹的遍歷是樹的一種重要的運算。所謂遍歷是指對樹中全部節點的信息的訪問,即依次對樹中每一個結點訪問一次且僅訪問一次,咱們把這種對全部節點的訪問稱爲遍歷(traversal)。數據結構
樹的兩種重要的遍歷模式是深度優先遍歷和廣度優先遍歷。深度優先通常用遞歸,廣度優先通常用隊列。通常狀況下能用遞歸實現的算法大部分也能用堆棧來實現。app
從樹的root開始,從上到下、從左到右地遍歷整個樹的節點。機器學習
對於一顆二叉樹,深度優先搜索(Depth First Search)是沿着樹的深度遍歷樹的節點,儘量深的搜索樹的分支。
深度遍歷有重要的三種方法。這三種方式常被用於訪問樹的節點,它們之間的不一樣在於訪問每一個節點的次序不一樣。這三種遍歷分別叫作先序遍歷(preorder),中序遍歷(inorder)和後序遍歷(postorder)。
在先序遍歷中,咱們先訪問根節點,而後遞歸使用先序遍歷訪問左子樹,再遞歸使用先序遍歷訪問右子樹。
在中序遍歷中,咱們遞歸使用中序遍歷訪問左子樹,而後訪問根節點,最後再遞歸使用中序遍歷訪問右子樹。
在後序遍歷中,咱們先遞歸使用後序遍歷訪問左子樹和右子樹,最後訪問根節點。
1 class Node: 2 """樹的節點類""" 3 def __init__(self, item): 4 self.elem = item 5 self.lchild = None 6 self.rchild = None 7 8 9 class Tree: 10 """二叉樹""" 11 12 def __init__(self, root=None): 13 """初始化根節點""" 14 self.root = root 15 16 def add(self, elem): 17 """爲樹添加節點""" 18 node = Node(elem) 19 # 若是樹是空的,則爲根節點賦值 20 if self.root is None: 21 self.root = node 22 else: 23 queue = [] 24 queue.append(self.root) 25 # 對已有節點進行層次遍歷 26 while queue: 27 # 彈出隊列的第一個元素(先進先出) 28 cur_node = queue.pop(0) 29 if cur_node.lchild is None: 30 cur_node.lchild = node 31 return 32 elif cur_node.rchild is None: 33 cur_node.rchild = node 34 return 35 # 若是左右子樹都不爲空,加入隊列繼續判斷 36 else: 37 queue.append(cur_node.lchild) 38 queue.append(cur_node.rchild) 39 40 def breadth_travel(self): 41 """廣度遍歷""" 42 if self.root is None: 43 return 44 queue = [self.root] 45 while queue: 46 cur_node = queue.pop(0) 47 print(cur_node.elem, end=" ") 48 if cur_node.lchild is not None: 49 queue.append(cur_node.lchild) 50 if cur_node.rchild is not None: 51 queue.append(cur_node.rchild) 52 53 def preorder(self, node): 54 """遞歸實現先序遍歷""" 55 if node is None: 56 return 57 print(node.elem, end=" ") 58 self.preorder(node.lchild) 59 self.preorder(node.rchild) 60 61 def midorder(self, node): 62 """遞歸實現中序遍歷""" 63 if node is None: 64 return 65 self.midorder(node.lchild) 66 print(node.elem, end=" ") 67 self.midorder(node.rchild) 68 69 def postorder(self, node): 70 """遞歸實現後序遍歷""" 71 if node is None: 72 return 73 self.postorder(node.lchild) 74 self.postorder(node.rchild) 75 print(node.elem, end=" ") 76 77 78 if __name__ == "__main__": 79 tree = Tree() 80 tree.add(0) 81 tree.add(1) 82 tree.add(2) 83 tree.add(3) 84 tree.add(4) 85 tree.add(5) 86 tree.add(6) 87 tree.add(7) 88 tree.add(8) 89 tree.add(9) 90 print("廣度遍歷:", end="") 91 tree.breadth_travel() 92 print() 93 print("先序遍歷:", end="") 94 tree.preorder(tree.root) 95 print() 96 print("中序遍歷:", end="") 97 tree.midorder(tree.root) 98 print() 99 print("後序遍歷:", end="") 100 tree.postorder(tree.root)
運行結果:
廣度遍歷:0 1 2 3 4 5 6 7 8 9 先序遍歷:0 1 3 7 8 4 9 2 5 6 中序遍歷:7 3 8 1 9 4 0 5 2 6 後序遍歷:7 8 3 9 4 1 5 6 2 0
答:先序與中序,或中序與後續。