考研數據結構筆記—堆排序
阿新 • • 發佈:2018-03-10
pre 最大 str 時間復雜度 時間 左右 OS wap -s
完全二叉樹是效率很高的數據結構,堆是一種完全二叉樹或者近似完全二叉樹,所以效率同樣極高。目前十分常用的排序算法、Dijkstra算法、Prim算法等都要用堆才能優化。
堆排序是一種選擇排序算法,與原序列的初始排列次序無關,即最好、最壞和一般情況排序的時間復雜度不變,均為O(nlgn)。而且,堆排序只需要一個記錄記錄元素大小的輔助空間(供交換使用),故空間復雜度為O(1)。正由於堆排序不僅時間復雜度小,而且空間復雜度O(1)也是最小,所以是用於排序的最佳選擇。
堆的定義
n個元素序列 { k0,k1,..., kn } 當且僅當滿足下列條件之一時,稱之為堆(其中 i = 0, 1, ..., n/2 向下取整)。
- ki <= k2i+1 且 ki <= k2i+2(最小堆)
- ki >= k2i+1 且 ki >= k2i+2(最大堆)
堆排序實現
方法1:
利用最小堆性質實現堆排序
/*交換數組中兩個元素的值*/ void swap(int *arr, int a, int b) { int temp = arr[a]; arr[a] = arr[b]; arr[b] = temp; } /*(小根)堆調整*/ void minHeapify(int *arr, int heapSize, int curNode) { /*找出當前節點和其左右節點三者的最小值*/ int minNode = curNode; int left = curNode * 2 + 1; int right = curNode * 2 + 2; if(left < heapSize && arr[left] < arr[minNode]) //左孩子存在且較小 minNode = left; if(right < heapSize && arr[right] < arr[minNode]) //右孩子存在且較小 minNode = right;if(minNode != curNode) //當前節點不是最小則需要交換 { swap(arr, minNode, curNode); minHeapify(arr, heapSize, minNode); //子節點需重新調整 } } /*構建堆*/ void createHeap(int *arr, int heapSize) { for(int i = heapSize/2 - 1; i >= 0; i--) //從最後一個非葉節點開始 { minHeapify(arr, heapSize, i); } } /*(最小)堆排序 *思想: *1、構建最小堆 *2、從最後一個元素開始只第二個元素將依次與首元素交換 *3、全局調整堆
*上面步驟2和步驟3將所有元素都與首元素交換,然後進行全局範圍的堆調整,利用最小堆的性質實現將所有元素按從小到大的方式排序 */ void heapSort(int *arr, int length) { createHeap(arr, length); //構建堆 for(int i = length-1; i > 0; i--) { swap(arr, 0, i); //與首元素交換 minHeapify(arr, length, 0); //調整堆 } }
方法2
利用最大堆性質實現堆排序
/*交換數組中兩個元素的值*/ void swap(int *arr, int a, int b) { int temp = arr[a]; arr[a] = arr[b]; arr[b] = temp; } /*(大根)堆調整*/ void maxHeapify(int *arr, int heapSize, int curNode) { /*找出當前節點和其左右節點三者的最小值*/ int maxNode = curNode; int left = curNode * 2 + 1; int right = curNode * 2 + 2; if(left < heapSize && arr[left] > arr[maxNode]) //左孩子存在且較小 maxNode = left; if(right < heapSize && arr[right] > arr[maxNode]) //右孩子存在且較小 maxNode = right; if(maxNode != curNode) //當前節點不是最小則需要交換 { swap(arr, maxNode, curNode); maxHeapify(arr, heapSize, maxNode); //子節點需重新調整 } } /*構建堆*/ void createHeap(int *arr, int heapSize) { for(int i = heapSize/2 - 1; i >= 0; i--) //從最後一個非葉節點開始 { maxHeapify(arr, heapSize, i); } } /*(最大)堆排序 *思想: *1、構建最大堆 *2、從最後一個元素開始只第二個元素將依次與首元素交換 *3、進行數組中當前元素前面的所有元素的局部調整堆 *上面步驟2和步驟3將所有元素都與首元素交換,將局部範圍內的最大值沈到後面,然後進行當前元素前面所有元素的局部範圍內的堆調整 *即在數組A中,當前元素索引為i,將A[i]與A[0]交換,將A[0,1,...,i]中最大的值放到A[i],然後進行A[0,1,...,i-1]堆調整, *將A[0,1,...,i-1]內的最大值放到A[0]中,待下一次交換使用,實現將局部的最大值依次沈到數組後面,完成排序 */ void heapSort(int *arr, int length) { createHeap(arr, length); //構建堆 for(int i = length-1; i > 0; i--) { swap(arr, 0, i); //與首元素交換 maxHeapify(arr, i, 0); //調整堆 } }
考研數據結構筆記—堆排序