1. 程式人生 > >【排序演算法】:堆排序

【排序演算法】:堆排序

介紹

堆排序(Heapsort)是指利用堆積樹(堆)這種資料結構所設計的一種排序演算法,它是選擇排序的一種。可以利用陣列的特點快速定位指定索引的元素。堆分為大根堆和小根堆,是完全二叉樹。大根堆的要求是每個節點的值都不大於其父節點的值,即A[PARENT[i]] >= A[i]。在陣列的升序排序中,需要使用的就是大根堆,因為根據大根堆的要求可知,最大的值一定在堆頂。

思想:
用升序建大堆,降序建小堆。(我們實現升序排序)

  1. 將初始待排序關鍵字序列(R1,R2….Rn)構建成大頂堆,此堆為初始的無序區;
  2. 將堆頂元素R[1]與最後一個元素R[n]交換,此時得到新的無序區(R1,R2,……Rn-1)和新的有序區(Rn),且滿足R[1,2…n-1]<=R[n];
  3. 由於交換後新的堆頂R[1]可能違反堆的性質,因此需要對當前無序區(R1,R2,……Rn-1)調整為新堆,然後再次將R[1]與無序區最後一個元素交換,得到新的無序區(R1,R2….Rn-2)和新的有序區(Rn-1,Rn)。不斷重複此過程直到有序區的元素個數為n-1,則整個排序過程完成。

時間複雜度:建堆的時間複雜度是O(n);調整堆的時間複雜度是lgn。堆排序的時間複雜度是O(nlgn);
空間複雜度:空間為O(1);
穩定性:不穩定;

程式碼實現

//堆排序
//升序建大堆

void AdjustDown(int* heap, int n, int parent)//向下調整
{
    int
child = parent * 2 + 1; while (child < n) { if (child + 1 < n && heap[child + 1] > heap[child]) ++child; if (heap[child]>heap[parent]) { swap(heap[child], heap[parent]); parent = child; child = parent
* 2 + 1; } else break; } } void HeapSort(int* arr, int len) { assert(arr); assert(len); int parent = (len - 2) >> 1; for (; parent >= 0; --parent) AdjustDown(arr, len, parent); //堆頂與最後一個數交換,除最後一個數,調整成大堆。迴圈。保證每個堆的最後一個數是最大的 for (int i = len - 1; i >= 0; --i) { swap(arr[0], arr[i]); AdjustDown(arr,i, 0); } }