#LEFT(i)和RIGHT(i)爲 i 節點的左右子孩子,以最大堆爲例。ios
首先輸入爲一個數組A和一個下標i。假定根節點爲LEFT(i)和RIGHT(i)的二叉樹都是最大堆,但這時A[i]有可能小於其孩子,這樣就違背了最大堆的性質。維護堆經過讓A[i]的值在最大堆中「逐級降低」,從而使得如下標i爲根節點的子樹從新遵循最大堆的性質。c++
主要過程:從A[i],A[LEFT(i)]和A[RIGHT(i)]中選出最大的,並將其下標存儲在largest中。數組
1.若是A[i]是最大的,那麼以 i 爲根節點的樹已是最大堆,維護結束。數據結構
2.不然,最大元素是 i 的某個孩子節點,則交換A[i]和A[largest]的值。從而使 i 及其孩子都知足最大堆的性質。在交換後,下標爲largest的節點的值是原來的A[i],因而以該節點爲根的子樹又有可能會違反最大堆的性質。所以,須要對該子樹遞歸進行維護堆的過程。dom
從初始輸入數組建成的徹底二叉樹的最後一個非葉節點開始,向上至根節點,每一個節點都進行維護堆,便可造成最大堆。函數
建堆完成後,已將輸入數組A[1...n]建成最大堆。由於數組中的最大元素總在根節點A[1]處,經過把它與A[n]互換,並把它放到正確位置。而後從堆中刪除節點n。此時,新的根節點可能會違背最大堆的性質。而後就要從根節點開始維護堆,構造一個新的最大堆。不斷重複這一過程,直到堆裏還剩一個節點。ui
import math.random
def print_tree(array): # 打印堆排序使用 """ 深度 前空格 元素間空格 1 7 0 2 3 7 3 1 3 4 0 1 """ # first=[0] # first.extend(array) # array=first index = 1 depth = math.ceil(math.log2(len(array))) # 由於補0了,否則應該是math.ceil(math.log2(len(array)+1)) sep = ' ' for i in range(depth): offset = 2 ** i print(sep * (2 ** (depth - i - 1) - 1), end='') line = array[index:index + offset] for j, x in enumerate(line): print("{:>{}}".format(x, len(sep)), end='') interval = 0 if i == 0 else 2 ** (depth - i) - 1 if j < len(line) - 1: print(sep * interval, end='') index += offset print() def sort(arr,start,end): if end == start * 2: if arr[start * 2] > arr[start]: arr[start * 2], arr[start] = arr[start], arr[start * 2] else: if end < start * 2 + 1: return else: left = arr[start*2] right = arr[start*2+1] if left>right and left > arr[start]: arr[start * 2 ], arr[start] = arr[start], arr[start * 2 ] sort(arr,start*2,end) if left<right and right > arr[start]: arr[start * 2+1], arr[start] = arr[start], arr[start * 2+1] sort(arr, start * 2+1, end) def heapfiy(arr): x = len(arr) - 1 n = x // 2 while n > 0: # print(n) sort(arr, n, x) n -= 1 # 如下是主函數 # 第一個0是佔位用 orignal_list=[0, 74, 73, 59, 72, 64, 69, 43, 36, 70, 61, 40, 16, 47, 67, 17, 31, 19, 24, 14, 20, 48, 5, 7, 3, 78, 84, 92, 97, 98, 99] print(orignal_list) # 第一次構建最大堆 heapfiy(orignal_list) # 打印樹 print_tree(orignal_list) x = len(orignal_list) - 1 while x != 1: # 交換最大的數和最後一個 orignal_list[1],orignal_list[x]=orignal_list[x],orignal_list[1] x-=1 # 因爲交換了,再也不是最大堆,從新構建最大堆 n=x//2 while n>0: sort(orignal_list,n,x) n-=1 # 打印最後結果 print_tree(orignal_list) print(orignal_list)
c++:spa
#include<iostream> using namespace std; void heapSort(int a[], int n); void maxHeap(int a[], int n); void buildMaxHeap(int a[], int n); int size; int main() { int a[] = { 9, 12, -3, 0, 6, 8, 15, 7 }; size= sizeof(a) / 4; heapSort(a, size); for (int i = 0; i < 8; i++) cout << a[i] << " "; return 0; } void heapSort(int a[], int n) { int i; buildMaxHeap(a, n); for (i = size; i>1; i--) { swap(a[0], a[i-1]); size = size - 1; maxHeap(a, 1); } } void buildMaxHeap(int a[], int n) { int i = n / 2; for (i; i > 0; i--) maxHeap(a, i); } void maxHeap(int a[], int n) { int leftChild, rightChild, largest; leftChild = 2 * n; rightChild = 2 * n + 1; int q = sizeof(a); if (leftChild<=size&&a[leftChild-1]>a[n-1]) largest = leftChild; else largest = n; if (rightChild<=size&&a[rightChild-1]>a[largest-1]) largest = rightChild; if (largest != n) { swap(a[n-1], a[largest-1]); maxHeap(a, largest); } }
優先隊列是一種用來維護由一組元素構成的集合S的數據結構,其中每個元素都有一個相關值,稱爲關鍵字。code
1.返回S中具備最大關鍵字的元素orm
2.去掉並返回S中具備最大關鍵字的元素
3.將元素x的關鍵字值增長到k,這裏假設k的值不小於原關鍵字的值。
4.把元素x插入到集合S中
如下給出實現思想(在已建成最大堆的基礎上):
1.返回根節點便可
2.經過維護堆(具體過程參考堆排序),便可實現去掉最大關鍵字
3.經過不斷與其父節點比較和交換,尋找正確位置,維護最大堆的性質
4.在堆中爲x增長一個葉節點,而後經過3的過程爲x尋找正確位置