堆排序之 大顶堆和小顶堆 c语言
百度得到的堆定義如下:
堆的定義如下:n個元素的序列{k1,k2,ki,…,kn}當且僅當滿足下關系時,稱之為堆。 (ki <= k2i,ki <= k2i+1)或者(ki >= k2i,ki >= k2i+1), (i = 1,2,3,4...n/2)? ? ? ? 當ki <= k2i的時候,稱之為小頂堆,反之則稱之為大頂堆。堆排序時間復雜度好壞情況均為nlogn,效率在一眾排序算法中排得上第二了。此外,在很多面試題中,堆排序是一種非常高效的解決問題手段,比如查找前100萬個數中的最大值或者最小值。此時如果使用堆排序的話,不僅滿足時間復雜度要求,空間復雜度也可滿足。堆排序聽起來挺難的,其實實現是相當簡單。
? ? ? ? 堆的圖形化顯示和二叉樹類似,對于小頂堆,任意節點的左右子樹都小于它,堆頂為最小元素。對于大頂堆,任意節點都大于其左右子樹,堆頂為最大元素,定義上容易理解。堆排序是基于數組的,因為數組下標和它特別匹配。如果使用c語言實現堆排序,注意分配數組的時候多分配一個存儲單元,這樣就可以直接從下標1開始,免得從0開始還得處理下標問題,得不償失。
? ? ? ? 堆的基本操作包括:查詢,添加,刪除,無序數組初始化建堆等。
1.? ? ? ?先從數組初始化建堆開始,首先要找到堆中最后一個非終端節點,下標為size/2。至于這個值是如何得到的??梢宰孕杏嬎阆?#xff0c;這里給個提示,沒有孩子節點或者有一個孩子節點兩種情況。得到這個非終端節點下標后,可以從它開始,自下往上調整堆,根據堆的性質(大頂堆或者小頂堆),將當前元素和孩子節點比較,然后調整合適位置。代碼比較簡單,如下:
//調整s的位置,s+1 ~ end為排好序的堆 void heapAdjust(pheap p, int s, int end) {int i, j;j = 2 * s;for (;j <= end; j*=2){//這里給出的是大頂堆,如果是小頂堆的話,將比較符號以及下面的操作進行反向處理即可。if (j < end && p->data[j] < p->data[j+1])j++;if (p->data[s] >= p->data[j]) break;swap(p->data + s, p->data + j);s = j;}return ; }void heapSort(pheap p) {int i, size = p->len;//從非終端節點,自底向上調整堆for (i = size/2; i >= 1; i--)heapAdjust (p, i, p->len); }2.? 查詢操作,當然就是從頂部開始往下查嘍,這點和普通的二叉搜索樹查詢一樣,比較大小,然后再和左右子樹比較。
3. 插入操作,通常都是追加到尾部,然后自底向上比較找到合適位置。
4. 刪除操作的話,一般都是刪除堆頂元素,這時候將堆底元素提到堆頂,然后重新調整堆即可。調整操作于初始化無序數組類似。
?
以上就是堆排序的內容,相比插入排序、歸并排序、快速排序,我覺得堆排序算是相當高效的一種排序算法。此外,相比于利用AVL、紅黑樹等高級數據結構實現的排序而言,堆排序實現代碼特別簡潔,和冒泡排序有的一拼,適合手撕排序。
參考資料:
1.?數據結構?: C語言版/ 嚴蔚敏,吳偉民編著
=============================================================================================
Linux應用程序、內核、驅動開發交流討論群(745510310),感興趣的同學可以加群討論、交流、資料查找等,前進的道路上,你不是一個人奧^_^。
總結
以上是生活随笔為你收集整理的堆排序之 大顶堆和小顶堆 c语言的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: leetcode 703. 数据流中
- 下一篇: leetcode 101. 对称二叉树