堆排序是一種選擇排序,其時間複雜度為o(nlogn)。
堆的定義
n個元素的序列當且僅當滿足下列關係之一時,稱之為堆。
情形1:ki
<= k2i 且ki
<= k2i+1 (最小化堆或小頂堆)
情形2:ki >= k2i 且ki >= k2i+1 (最大化堆或大頂堆)
其中i=1,2,…,n/2向下取整;
若將和此序列對應的一維陣列(即以一維陣列作此序列的儲存結構)看成是乙個完全二叉樹,則堆的含義表明,完全二叉樹中所有非終端結點的值均不大於(或不小於)其左、右孩子結點的值。
由此,若序列是堆,則堆頂元素(或完全二叉樹的根)必為序列中n個元素的最小值(或最大值)。
例如,下列兩個序列為堆,對應的完全二叉樹如圖:
若在輸出堆頂的最小值之後,使得剩餘n-1個元素的序列重又建成乙個堆,則得到n個元素的次小值。如此反覆執行,便能得到乙個有序序列,這個過程稱之為堆排序。
堆排序(heap sort)只需要乙個記錄元素大小的輔助空間(供交換用),每個待排序的記錄僅占有乙個儲存空間。
一般用陣列來表示堆,若根結點存在序號0處, i結點的父結點下標就為(i-1)/2。i結點的左右子結點下標分別為2*i+1和2*i+2。
(注:如果根結點是從1開始,則左右孩子結點分別是2i和2i+1。)
如第0個結點左右子結點下標分別為1和2。
如最大化堆如下:
左圖為其儲存結構,右圖為其邏輯結構。
實現堆排序需要解決兩個問題:
1.如何由乙個無序序列建成乙個堆?
2.如何在輸出堆頂元素之後,調整剩餘元素成為乙個新的堆?
先考慮第二個問題,一般在輸出堆頂元素之後,視為將這個元素排除,然後用表中最後乙個元素填補它的位置,自上向下進行調整:首先將堆頂元素和它的左右子樹的根結點進行比較,把最小的元素交換到堆頂;然後順著被破壞的路徑一路調整下去,直至葉子結點,就得到新的堆。
我們稱這個自堆頂至葉子的調整過程為「篩選」。
從無序序列建立堆的過程就是乙個反覆「篩選」的過程。
初始化堆的時候是對所有的非葉子結點進行篩選。
最後乙個非終端元素的下標是[n/2]向下取整,所以篩選只需要從第[n/2]向下取整個元素開始,從後往前進行調整。
比如,給定乙個陣列,首先根據該陣列元素構造乙個完全二叉樹。
然後從最後乙個非葉子結點開始,每次都是從父結點、左孩子、右孩子中進行比較交換,交換可能會引起孩子結點不滿足堆的性質,所以每次交換之後需要重新對被交換的孩子結點進行調整。
有了初始堆之後就可以進行排序了。
堆排序是一種選擇排序。建立的初始堆為初始的無序區。
排序開始,首先輸出堆頂元素(因為它是最值),將堆頂元素和最後乙個元素交換,這樣,第n個位置(即最後乙個位置)作為有序區,前n-1個位置仍是無序區,對無序區進行調整,得到堆之後,再交換堆頂和最後乙個元素,這樣有序區長度變為2。。。
不斷進行此操作,將剩下的元素重新調整為堆,然後輸出堆頂元素到有序區。每次交換都導致無序區-1,有序區+1。不斷重複此過程直到有序區長度增長為n-1,排序完成。
首先,建立初始的堆結構如圖:
然後,交換堆頂的元素和最後乙個元素,此時最後乙個位置作為有序區(有序區顯示為黃色),然後進行其他無序區的堆調整,重新得到大頂堆後,交換堆頂和倒數第二個元素的位置……
重複此過程:
最後,有序區擴充套件完成即排序完成:
由排序過程可見,若想得到公升序,則建立大頂堆,若想得到降序,則建立小頂堆。
假設排列的元素為整型,且元素的關鍵字為其本身。
因為要進行公升序排列,所以用大頂堆。
根結點從0開始,所以i結點的左右孩子結點的下標為2i+1和2i+2。
如何進行結構體排序
1.乙個結構體中有三個元素,按照其中乙個元素進行降序排列 先定義乙個結構體 struct node a 1005 然後寫排序 int cmp node a,node b 在main函式裡面用sort進行排序 sort a,a n,cmp 2 排序要求 按分數從高到低輸出上線考生的考號與分數,其間用1...
python 如何進行元組排序
python list 可以直接進行sort排序,預設是按照從小到大進行排序.現在有個需求 要按照元組的第乙個元素進行公升序,但是按照第二個元素進行降序 如下是個取巧的辦法,這裡的100根據數值範圍進行調整,思路是選擇乙個函式,對第乙個元素是增函式,第二個元素是減函式 sorted l l 0,2 ...
如何進行Monkey Test
一 簡介 monkey是android中的乙個命令列工具,可以執行在模擬器裡或實際裝置中。它向系統傳送偽隨機的使用者事件流 如按鍵輸入 觸控螢幕輸入 手勢輸入等 實現對正在開發的應用程式進行壓力測試。monkey包括許多選項,它們大致分為四大類 基本配置選項,如設定嘗試的事件數量 執行約束選項,如設...