前段時間寫了這篇文章幾個常見排序演算法的實現,僅僅是對自己所學知識的一點總結。這不寒假這段時間又在看《演算法》一書,前兩章也是在講基礎排序演算法,感覺書中的思路比我自己總結的好太多,於是就抽出時間來再寫一寫新的理解和體會。也算是對前面那篇文章的一點補充吧。
說到堆排序,我們應該不陌生,以前在資料結構課堂上也曾學習過。但是當時老師直接就引出了堆排序,加上當時聽課也沒有特別認真,於是就聽的雲裡霧裡。現如今看了《演算法》中的講解,覺得有點收穫,於是便進行一下總結。說到堆排序,首先應當提優先佇列。下面我們就先來了解一下優先佇列。
優先佇列顧名思義是乙個佇列,不過當然有別於我們所熟知的先入先出佇列,否則也就不必冠以優先兩字了。優先是指優先順序,優先佇列中的元素需要根據優先順序順序來出隊。我們可以規定元素的值越大,優先順序越高,於是優先佇列中每次出隊的元素都是最大的元素。這種資料結構的實現請見優先佇列,當然也可以實現每次從佇列中刪除最小元素的優先佇列。優先佇列有多種實現方法,比較優秀且經典的實現是基於二叉堆的實現。優先佇列應用廣泛,常見的如根據優先順序進行任務排程、在大量資料中找出topm、還有一會就要介紹的堆排序演算法。
topm問題
既然說到了優先佇列,那就說一下使用優先佇列求解topm的方法。比如在輸入的資料中找出m個最大的元素。如果不使用優先佇列,我們可以先把輸入資料排序,然後從中找出最大的m個。這種方式在資料資料量較小時還可行,但是當輸入資料非常龐大時就不可能了,首先對大量資料排序是個不簡單的問題,再有這種方法所需的計算機記憶體也不能接受。但是使用了優先佇列情況就不同了,我們可以不對輸入資料進行排序,需要的記憶體也只是常熟級別。我們只需要直接將輸入資料按照輸入順序插入優先佇列,並固定佇列的容量為m+1,每當佇列中的元素數量達到m+1時候,就刪除其中最小的元素。這樣當所有元素都輸入完之後,佇列中的m個元素即是所有輸入資料中最大的m個。
堆分成大根堆和小根堆,當一棵二叉樹的每個結點都大於等於它的兩個子結點時,被稱為堆有序,這個堆為大根堆。當每個結點都小於等於它的兩個子結點時,這個堆為小根堆。在大根堆中,根節點是最大的結點。二叉堆是一組能夠用堆有序的完全二叉樹排序的元素。我們可以用陣列來實現完全二叉樹,陣列的索引(不使用第乙個位置0)對應完全二叉樹中結點的標號。由此便可以簡潔的實現堆的有序化。具體的實現請見上文中提到的優先佇列的**鏈結。
講到正題了,堆排序就是使用二叉堆這種資料結構進行排序,主要分成兩個步驟,先把輸入資料構造成乙個堆,然後再進行排序。那麼怎麼構造堆呢?一種方法是從堆頂開始構造,類似於把每個元素依次插入優先佇列,每插入乙個元素,進行一次堆的有序化。另一種方法是從堆底(陣列末端,即完全二叉樹中結點標號大的一端)開始構造,因為陣列的每個位置都已經是乙個子堆的根節點了,並且當乙個結點的兩個子結點都是堆時,可以把這兩個堆合併成乙個堆。類似於把多個子堆不斷的合併,這種方法比從堆頂開始構造堆更加高效。堆構造完成後就是進行排序了,忘了說,堆排序也是基於原址的。當堆構造好之後,堆頂(根元素)即為最大的元素,將這個元素和堆底(陣列末端)交換,即完成了乙個元素的排序。然後把堆的大小縮小一,再進行堆的有序化。重複進行這樣的操作,直到堆的大小為1,整個陣列有序。這個過程有些類似於選擇排序,但是比選擇排序需要的比較次數要少的多,因為堆提供了一種在未排序元素中找到最大元素的有效方法。
以上就是堆排序內容的一點總結,不同的排序演算法有不同的適用場景,比如當穩定性很重要而且記憶體又不是問題時,歸併排序可能是最好的選擇;但是當執行時間很重要時,快速排序便可能是更好的選擇。寫這些文章,是希望自己能夠理解種種不同演算法的思想,並了解其適用場景。了解多種不同的思考方式,從不同的角度看待問題,我想不只是演算法學習上,還有思維能力上,甚至生活上,大概都能從中受益吧。
演算法基礎 排序 堆排序
headsort2 是我自己想的,感覺這麼寫可以。驗證是ok的。區別等我問問。import com.alibaba.fastjson.json author wangtb date 2019 09 29 23 02 public class heapsort heapsort arr heapsor...
C 演算法基礎之排序 堆排序
今天,大白跟大家玩玩堆排序。基本思想 堆排序是利用堆 大根堆或者小根堆 的特點進行排序。啪啦啪啦一大堆。以建最小堆為例 簡言之,就是將無序區看成乙個完全二叉樹,利用完全二叉樹用陣列儲存是的特點,進行排序。建堆 從序列的末尾開始,先找出孩子中的較小值,然後和雙親比較,如果小於雙親,則交換位置。排序 進...
基礎排序演算法 堆 和堆排序
堆是一種靈巧,部分有序的資料結構,它適合用來實現優先佇列。優先佇列是元素的乙個集合,其中每個元素都包含乙個被稱作元素優先順序的可排序屬性,優先佇列支援下面的操作 找出乙個具有最高優先順序的元素 一般是最大或者最小 刪除乙個具有最高優先順序的元素 新增乙個元素到集合中去 定義 堆可以定義為一根二叉樹,...