排序演算法之堆排序

2021-08-30 08:17:23 字數 1693 閱讀 5205

堆是具有以下性質的完全二叉樹:每個節點都大於或等於其左右孩子節點的值,稱之為大頂堆;反之每個節點都小於或等於其左右孩子的值,稱之為小頂堆。

對於堆的實現,我們可以用陣列來表示元素的位置關係,如果乙個具有12個節點的堆(小頂堆)如下圖所示:

那我們使用陣列arr[0..11]的形式表示如下:

數中常見的函式形式如下所示:

root = 0

leftchild(i) = 2*i + 1

rightchild(i) = 2*i +2

parent(i) = (i-1)/2

在講解 堆排序前,先看看兩個關鍵的函式。堆排序實現的原理,就是這兩個函式實現的原理,我們先將該兩個函式名定義為siftup 和 siftdown

siftup

當x[0...n-1] 是堆時即heap(0,n-1),在x[n]位置放置乙個元素,可能不滿足x[0...n]具有堆的性質,即heap(0,n)不成立。那麼siftup的作用就是通過調整使heap(0,n)成立。 該函式名就表明了實現的策列:將新增的新元素盡可能地向上篩選,向上篩選是通過和父節點交換位置來實現。 下圖(從左到右)演示了新增 元素13 在堆中 向上交換的過程(在新增新元素13之前,該結構滿足堆的性質)

注意點:在上圖中,除了帶圈節點(新增節點或者新增節點被交換後的位置節點,後面用節點i表示) 和其父節點 可能不滿足堆性質外,但其他地方都滿足 堆的性質。那新增乙個新節點siftup調整堆的偽**就是 : 先for迴圈else

private int getrightchildindex(int p)

private int getparentindex(int c)

public void siftup(int date)}}

/***

* @param date

* @param length 表示date的前多少個元素需要進行heap調整

*/public void siftdown(int date,int length)

system.out.println("陣列調整後:"+printdate(date));

}public static string printdate(int date)else

}return builder.tostring();

}}列印結果:

之前學習堆排序的過程中,在網上看了一些blog,不過 一上來直接講解了演算法的流程(沒有講解本文中的兩個重要的函式),看的是一知半解。 後來看到程式設計珠璣 第二版 第11章  對 堆排序的表述後,恍然大悟。  所以在我們學習演算法的時候,有的時候需要對演算法的本質或者說對演算法的過程抽象 需要理解。  在理解本質後的基礎上再學習該演算法包括對演算法的運用,就會事半功倍! 如果需要了解更詳細的演算法思路,可以自行參考 程式設計珠璣 第二版 第11章 

程式設計珠璣 第二版 第11章節

排序演算法之堆排序

前言 今天我來介紹下堆排序,在寫堆排序 之前,我們要知道堆的概念!堆的定義 n個關鍵字序列kl,k2,kn稱為 heap 當且僅當該序列滿足如下性質 簡稱為堆性質 1 ki k 2i 且ki k 2i 1 1 i n 當然,這是小根堆,大根堆則換成 號。k i 相當於二叉樹的非葉子結點,k 2i 則...

排序演算法之堆排序

堆排序演算法是選擇排序的一種,該演算法只是通過堆,最大堆 或者最小堆選擇出乙個待排序序列中的最大值,或者最小值。要想實現堆排序演算法,就需要構建什麼堆,這裡也最小堆為例。說明什麼是堆,怎麼構建乙個堆。假設待排序序列為a n 為乙個陣列。陣列的長度為n 陣列下標為 0,1,2,i,2i,2i 1 n ...

排序演算法之堆排序

宣告 本博文 為樓主親自編寫並測試,其它內容引用至我一直很崇拜的牛人morewindows。他對排序演算法的講解通俗易懂,給人一種耳目一新的感覺。堆排序與快速排序 歸併排序 一樣都是時間複雜度為o n logn 的幾種常見排序方法。最小堆的講解以及最小堆元素的插入和刪除參見最小堆操作。以下繼續引用以...