【排序演算法】:堆排序
阿新 • • 發佈:2019-02-07
介紹
堆排序(Heapsort)是指利用堆積樹(堆)這種資料結構所設計的一種排序演算法,它是選擇排序的一種。可以利用陣列的特點快速定位指定索引的元素。堆分為大根堆和小根堆,是完全二叉樹。大根堆的要求是每個節點的值都不大於其父節點的值,即A[PARENT[i]] >= A[i]。在陣列的升序排序中,需要使用的就是大根堆,因為根據大根堆的要求可知,最大的值一定在堆頂。
思想:
用升序建大堆,降序建小堆。(我們實現升序排序)
- 將初始待排序關鍵字序列(R1,R2….Rn)構建成大頂堆,此堆為初始的無序區;
- 將堆頂元素R[1]與最後一個元素R[n]交換,此時得到新的無序區(R1,R2,……Rn-1)和新的有序區(Rn),且滿足R[1,2…n-1]<=R[n];
- 由於交換後新的堆頂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);
}
}