堆排序解剖

2021-07-30 11:17:40 字數 2012 閱讀 8518

堆排序

是一種資料結構,可以把堆看成一棵完全二叉樹,這棵完全二叉樹滿足:任何乙個非葉結點的值都不大於(或不小於)其左右孩子結點的值。若父親大孩子小,叫大頂堆;若父親小孩子大,則這樣的堆叫做小頂堆

二叉樹:每個結點最多只有兩棵子樹,即二叉樹中結點的度只能為0、1、2。子樹有左右之分,不能顛倒。

滿二叉樹:在一棵二叉樹中,如果所有的分支結點都有左孩子和右孩子結點,並且葉子結點都集中在二叉樹的最下一層。另一種定義:一棵深度為k且有個結點的二叉樹稱為滿二叉樹。

完全二叉樹:深度為k,有n個結點的二叉樹,當且僅當其每乙個結點都與深度為k的滿二叉樹中編號從1至n的結點一一對應時,稱之為完全二叉樹。通俗來講,一棵完全二叉樹是由一棵滿二叉樹從右至左從下而上,挨個刪除結點所得到的。

堆排序的思想:將乙個無序序列調整為乙個堆,就可以找出這個序列的最大(或最小)值,然後將找出的這個值交換到序列的最後(或最前),這樣有序序列元素增加·個,無序序列中元素減少1個,對新的無序序列重複這樣的操作,就實現了排序。

l  將原始序列化為乙個完全二叉樹。

l  從無序序列所確定的完全二叉樹的第乙個非葉子結點開始,從右至左,從下至上,對每乙個結點進行調整,最終將得到乙個大頂堆。

對結點的調整方法:將當前結點(假設為a)的值與其孩子結點進行比較,如果存在大於a值的孩子結點,則從中選出最大的乙個與a交換。當a來到下一層的時候重複上述過程,直到a的孩子結點值都小於a的值為止。

l  將當前無序序列中第乙個元素,反映在樹中是根節點(假設為a)與無序序列中最後乙個元素交換(假設為b)。a進入有序序列,到達最終位置。無序序列中元素減少1個,有序序列中元素增加1個。此時只有結點b可能不滿足堆的定義,對其進行調整。

l  重複3)中的過程,知道無序序列中的元素剩下1個時排序結束

/**

* 堆排序

* @author 卡羅-晨

* */

public class heapsort

/*** 用於刪除乙個最大值和建立堆

* @param a 無序序列

* @param i 過濾下來的位置

* @param n 堆的邏輯大小

*/private static > void percdown(t a,int i,int n)

for(int i=a.length-1;i>0;i--)

}}

對於percdown()方法來說,顯然child走的是一條從當前結點到葉子結點的路徑,完全二叉樹的高度為log(n+1),即對每個結點調整的時間複雜度為o(logn

)。對於heapsort()方法,基本操作總數應該是兩個並列的for迴圈中基本操作的次數相加,第乙個迴圈的基本操作次數為o(logn

)*n/2,第二個迴圈基本操作次數為o(logn

)*(n-1),因此整個演算法的基本操作次數問為o(logn

)*n/2+o(logn

)*(n-1),化簡後得其時間複雜度為o(nlogn

)

從演算法**可以看出,本演算法的額外空間只有乙個tmp,因此額外空間複雜度為o(1)。

注意:堆排序的最壞情況下的時間複雜度也是o(nlogn

),這是它相當於快速排序的最大優點,堆排序的空間複雜度為o(1),在所有時間複雜度為o(nlogn

)的排序中是最小的,這也是其一大優點,堆排序適合的場景是記錄數很多的情況。

堆排序 堆排序優化 索引堆排序

堆排序 堆排序優化 索引堆排序 注 堆排序 索引堆排序 都是不穩定的排序。注 索引最大堆排序有誤!有沒有大神可以指點一二?1 堆 所有元素 都從索引0開始 父親結點索引 i 左孩子結點索引 2i 1 右孩子結點索引 2i 2 左後乙個非葉子結點索引 n 1 2 用於構建堆,從最後乙個非葉子結點索引開...

堆排序 堆排序優化 索引堆排序

堆排序 堆排序優化 索引堆排序 注 堆排序 索引堆排序 都是不穩定的排序。注 索引最大堆排序有誤!有沒有大神可以指點一二?1 堆 所有元素 都從索引0開始 父親結點索引 i 左孩子結點索引 2i 1 右孩子結點索引 2i 2 左後乙個非葉子結點索引 n 1 2 用於構建堆,從最後乙個非葉子結點索引開...

堆排序 模擬堆排序

838.堆排序 輸入乙個長度為n的整數數列,從小到大輸出前m小的數。輸入格式 第一行包含整數n和m。第二行包含n個整數,表示整數數列。輸出格式 共一行,包含m個整數,表示整數數列中前m小的數。資料範圍 1 m n 1051 m n 105,1 數列中元素 1091 數列中元素 109 輸入樣例 5 ...