# 二叉樹的遍歷# 對二叉樹中的全部元素不重複的訪問一遍# 廣度優先遍歷# 層序遍歷# 從第一層開始,沒一層從左至右遍歷元素# 深度優先遍歷# 假設樹的根節點爲D,左子樹爲L,右子樹爲R,且要求L必定在R以前,則有如下遍歷方式:# 前序遍歷:也叫先序遍歷,也叫先根遍歷,DLR# 中序遍歷:也叫中根遍歷,LDR# 後序遍歷:也叫後根遍歷,LRD# 遍歷序列:將樹中全部元素遍歷一遍後,獲得的元素的序列,將層次結構轉換成了線性結構# 堆排序# 堆是一個徹底二叉樹# 每一個非葉子結點的值都要大於或者等於其左右孩子結點的值,稱爲大頂堆# 每一個非葉子結點的值都要小於或者等於其左右孩子結點的值,稱爲小頂堆# 根結點必定是大頂堆中的最大值,必定是小頂堆中的最小值# 例子:構建一個徹底二叉樹(序列 -> 徹底二叉樹 -> 大頂堆 -> 排序 - > 大頂堆 -> 排序 ...)# 待排序數字爲:30 20 80 40 50 10 60 70 90# 構建一個徹底二叉樹存放數據,並根據性質5對元素編號,放入順序的數據結構中# 性質5:按層依次編號# 構建一個列表爲[0, 30, 20, 80, 40, 50, 10, 60, 70, 90]***# 0爲補位,由於列表下表從0開始,想從1開始進行使用# 構建大頂堆的核心算法# 度數爲2的結點A,若是它的左右孩子結點的最大值比它大,將這個最大值和該結點交換# 度數爲1的結點A,若是它的左孩子的值比它大,則交換# 若是結點A被交換到新的位置,還須要和其孩子結點重複上面的過程# 構建大頂堆 - 起點結點的選擇# 從徹底二叉樹的最後一個結點的雙親結點開始,即最後一層的最右邊葉子結點的父節點開始***# 結點數爲n,則起始結點的編號n//2(性質5)# 構建大頂堆 - 下一個結點的選擇# 從起始結點開始向左找其同層結點,到頭後再從上一層的最右邊結點開始繼續向左逐個查找,直到根節點# 下一結點:n -> n-1 -> n-2 ... 1# 跟結點計算完畢後,若是有交換,則還須要向下對左右子樹進行再次排序# 大頂堆的目標# 確保每一個結點的值都比左右結點的值大# 排序# 將大頂堆根結點這個最大值和最後一個葉子結點交換,那麼最後一個葉子結點就是最大值,將這個葉子結點排除在待排序結點外# 從根結點開始(新的根結點),從新調整爲大頂堆後,重複上一步# 將列表打印成樹(堆排序輔助函數)import mathdef printTree(lst): treeLen = len(lst) treeLay = math.ceil(math.log2(treeLen + 1)) # 樹層數 index = 0 treeWidth = 2 ** treeLay - 1 # 樹寬度 for i in range(treeLay): for j in range(2**i): print('{:^{}}'.format(lst[index], treeWidth), end=' ') index += 1 if index >= treeLen: break treeWidth = treeWidth//2 print()lst = [1, 2, 3, 4, 5, 6, 7, 8, 9]printTree(lst)# 調整當前節點def heap_adjust(n, i, array:list): # array:list 表示array變量的類型是list ''' 調整當前節點核心算放 :param n: 待比較數字的個數 :param i: 當前節點的下標 :param array: 待排序數據 :return:None ''' while 2 * i <= n: # 性質5,=n只有左子樹 # 孩子結點判斷2i爲左孩子,2i+1爲右孩子 lChild_index = 2 * i maxChild_index = lChild_index # n=2i if n > lChild_index and array[lChild_index + 1] > array[lChild_index]: # n>2i說明還有右孩子 maxChild_index = lChild_index + 1 # n=2i+1 # 和子樹的根節點比較 if array[maxChild_index] > array[i]: array[i], array[maxChild_index] = array[maxChild_index], array[i] # 交換 i = maxChild_index # 被交換後,須要判斷是否還須要調整 else: break printTree(array) print('--------------------------')# 構建大頂堆def maxHeap(total, array:list): for i in range(total//2, 0, -1): heap_adjust(total, i, array) # 調整當前結點 return arraytotal = 9origin = [0,30, 20, 80, 40, 50, 10, 60, 70, 90]print('maxHeap is ')printTree(maxHeap(total, origin))# 結論:第一層是最大值,第二層必定有個次大值