堆和堆排序

2021-10-05 05:59:04 字數 3031 閱讀 3900

​ 認識堆以前,首先要明確兩個概念:滿二叉樹完全二叉樹

滿二叉樹:在一棵二叉樹中,如果所有分支節點都存在左子樹和右子樹,並且所有葉子都在同一層上,這樣的二叉樹稱為滿二叉樹。

完全二叉樹:對一棵具有 n 個節點的二叉樹按層序編號,如果編號為 i 的節點與同樣深度的滿二叉樹中編號為 i 的節點在二叉樹中的位置完全相同,則這棵二叉樹稱為完全二叉樹。

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

​ 該方法的思路是把陣列先全部載入到陣列裡,然後按照完全二叉樹的結構從下往上,從右往左逐步建堆,最後把整個二叉樹擴充套件成堆。

時間複雜度分析:

​ 設有 n 個節點,則這 n 個節點構成的完全二叉樹深度為 log(n),把高度設為 h

​ 第 m 層最多的節點個數是 2^(m) ,每個節點需要下移的最多的次數是 (h - m) 次,則時間複雜度

​ t = 2^(h - 1) * 1 + 2^(h - 2) * 2 + 2^(h - 3) * 3 + … + 2^1 * (h - 1) + 2^0 * (h) (1)

等式兩邊同乘 2

2t=2^h * 1 + 2^(h - 1) * 2 + 2^(h - 2) * 3 + 2^(h - 3) * 4 + …+2^1 * (h) (2)

用 (2) 式減 (1) 式得

t = 2^h + 2^(h - 1) + 2^(h - 2) + … + 2^1 - 2^0 (3)

根據等比數列求和公式得

t = 2^(h + 1) - h - 1

h = log2(n),所以得 t = n - log2(n) + 1,即時間複雜度為 o(n)

**

void

createheap()

;int currentpos =

(arr.length -2)

/2;//最後乙個非葉子節點

while

(currentpos >=0)

}//構建大根堆

void

filterdown

(int

arr,

int start,

int end)

if(temp < arr[j]

)else

} arr[i]

= temp;

}

​ 該方法的思路是每次把資料插入到堆的最後乙個位置,逐步把該節點往上公升,直到公升不動為止。

時間複雜度:這種方法的時間複雜度很好分析,一共 n 個節點,每個節點最大比較 log2(n) 次,所以時間複雜度就是 n * log2(n)

void

createheap()

;//相當於是乙個乙個插入到堆的末尾,再向上調整成堆

int currentpos =0;

while

(currentpos < arr.length)

for(

int i : arr)

}void

filterup

(int

arr,

int end)

else

break;}

else

break;}

arr[i]

= temp;

//移動到最後的位置,這種方式減少了交換次數

}

​ 第一種建堆方式主要用於堆元素已經確定好的情況,第二種方式主要用於動態增加元素來建堆。插入建堆的過程也常用於建立優先佇列的應用。

​ 堆排序的基本思想就是把待排序的序列造成乙個大頂堆。此時,整個序列最大的值就是堆頂的根節點。將它移走(為了節省空間,就直接和最後乙個節點互換位置了),然後將剩餘 n - 1 個節點重新構造成乙個堆,這樣就會得到 n 個元素中的次小值。如此反覆執行,便能得到乙個有序序列了(如果用了節省空間的方法,那麼大根堆得到的是公升序序列,小根堆得到的是降序序列)。

時間複雜度

​ 共需要移走 n 個節點,每移走乙個節點重新建堆需要 log(n) 的時間,所以時間複雜度為 n * log(n)

空間複雜度

​ 沒有開闢額外的空間,所以是 o(1),如果不用節省空間的方法,空間複雜度是 o(n)。

​ 因為堆排序存在跳躍,所以堆排序是不穩定的(隨手畫一下就發現了)。

void

createheap()

;int currentpos =

(arr.length -2)

/2;//最後乙個非葉子節點

while

(currentpos >=0)

}//構建大根堆

void

filterdown

(int

arr,

int start,

int end)

if(temp < arr[j]

)else

} arr[i]

= temp;

}//只在建好的堆上加個排序方法即可

void

sort

(int

arr)

}

堆和堆排序

堆是一種靈巧的 部分有序的資料結構,它尤其適合用來實現優先佇列。優先佇列是元素的乙個集合,其中每個元素都包含乙個被稱為元素優先順序的可排序屬性。優先佇列支援下面的操作 通過採用堆這種資料結構可以高效實現這些操作。下文分兩部分 第一部分介紹堆 第二部分講解堆排序。堆可以定義為一棵二叉樹,樹的節點中包含...

堆和堆排序

這個題大意是有乙個資料結構支援兩種操作a與 get操作,其中 a x表示插入 x.get i 表示返回結構中的第 i小的數.給你 a和get操作的順序和引數 現在要你對每個 get輸出值 題解 每次取第k小元素,k不斷更新。使用兩個堆,來完成。小頂堆負責選出最小的元素,大頂堆負責選出k個元素中最大的...

堆和堆排序

堆排序演算法 優先佇列 堆的性質的維護,以下都以最大堆為例。堆的維護的主要思想是 逐層下降 舉例 某個結點i,假設其左右子結點left i right i 都已經是最大堆,那麼需要調節 或者說是調換 i,left i right i 的值,並保證調換後的子樹繼續調換下去直到子樹繼續滿足堆的性質。首先...