堆排序以及TopK大頂堆小頂堆求解方式(js版)

2021-10-20 13:15:56 字數 2611 閱讀 7096

堆排序是一種選擇排序,時間複雜度o(nlogn),空間複雜度o(1)。

資料結構底層是陣列,通過索引之間的關係可看二叉樹,父結點總是大於或者小於孩子結點。這就是堆的結構。

剛初始完的堆是佔據整個陣列的。

開始排序後,陣列分為兩個部分!前面是堆,後面是已排序完的有序子陣列。

排序時,堆頂元素和堆尾元素會交換,有序子陣列長度+1,堆長度-1;此時,原堆尾元素佔據了堆頂,可能會破壞了堆結構,所以,需要堆化,也就是堆頂元素要保持最大或者最小。

當堆只有乙個元素,自動加入有序子陣列;這時有序子陣列佔據整個陣列。排序完成。

將普通陣列初始為堆。

把陣列arr看成乙個二叉樹,父結點與孩子結點的關係:root:i , leftchild:2i+1, rightchild:2i+2

找到索引最大的非葉子節點。陣列長度length,假設length- 1= 2i + 1,則i=length/2 - 1。所以索引最大的非葉子結點是arr[i]。

堆化。也就是將[i,length - 1]的陣列變成堆,然後i - 1,使堆長度+1,再堆化,這樣反覆操作,直到i == 0,讓堆佔滿整個陣列。

//初始堆

for(

let i =

(arr.length >>1)

-1; i >=

0; i--

)

用父結點與孩子結點比較,如果父結點比孩子結點大,則不調整位置(最大堆);否則,將孩子結點與父結點交換。

如果發生交換的話,再將孩子結點作為父結點,與它的孩子節點再作比較。直到葉子結點。

//compare=(a,b)=>a>b :最大堆;compare=(a,b)=>a/**

* i 堆頂索引

* end 堆尾索引+1

* compare 控制是最大堆還是最小堆

*/function

adjustheap

(arr, i, end, compare)if(

!compare

(tmp, arr[childindex]))

else

} arr[parentindex]

= tmp;

}

1.一開始,堆佔據整個陣列。取出堆頂元素,與堆尾元素交換。交換後,堆尾加入有序子陣列,堆長度-1。

2.所有堆元素加入有序陣列後,排序完畢。

3.小頂堆用於降序排序,大頂堆用於公升序排序。

for

(let j = arr.end-

1; j >

0; j--

)

function

sort

(arr, comparefunction)

let compare = comparefunction || defaultcompare;

for(

let i =

(arr.length >>1)

-1; i >=

0; i--

)for

(let j = arr.length -

1; j >

0; j--

)//排序完成

}//堆化

//compare=(a,b)=>a>b :大頂堆;compare=(a,b)=>a/**

* i 堆頂索引

* end 堆尾索引+1

* compare 控制是最大堆還是最小堆

*/function

adjustheap

(arr, i, end, compare)if(

!compare

(tmp, arr[childindex]))

else

} arr[parentindex]

= tmp;

}

拿小頂堆舉例來說,堆頂就是當前k個中最小的。如果最大的前k個元素都在這個堆中,那堆頂就是第k大的那個元素。

初始化堆,堆的大小為k。(直接拿陣列前k個元素初始就行)

從arr[k](第k+1個元素)開始和堆頂作比較,如果大於堆頂就和堆頂交換;交換後,堆頂可能不是堆中最小元素,所以需要堆化。

不斷地有更大的元素被換入堆中,並且堆頂又能保持堆中最小。

當arr[length-1]也比較完成後,堆中就包含了最大的k個元素了,並且堆頂arr[0]就是第k大的元素。時間複雜度o(nlogk)

function

findtopk

(arr, k, comparefunction)

let compare = comparefunction || defaultcompare;

for(

let i =

(k >>1)

-1; i >=

0; i--

)for

(let j = k +

1; j < arr.length; j++)}

return arr[0]

;//返回堆頂(topk)

}

還有乙個演算法能用o(n)解決topk問題,之後在做研究!

參考:

Java 堆排序 大頂堆 小頂堆

引用 堆排序 heapsort 是指利用堆這種資料結構所設計的一種排序演算法。堆積是乙個近似完全二叉樹的結構,並同時滿足堆積的性質 即子結點的鍵值或索引總是小於 或者大於 它的父節點。堆排序的平均時間複雜度為 nlogn 演算法步驟 1.建立乙個堆h 0.n 1 2.把堆首 最大值 和堆尾互換 3....

topk 堆排序 小頂堆

問題描述 假設需要我們在一堆海量資料中找出排名前k的資料 最好的方法是用最小堆排序,直接用前k個資料建立乙個小頂堆,然後遍歷剩餘的數,如果此數 堆頂的數,則將此數和堆頂的數交換,然後從堆頂向下調整堆,使其重新滿足小頂堆。說明 堆的儲存 一般用陣列來表示堆,第i個節點的父節點下標為i 2 1 它的左右...

排序演算法 堆排序(大頂堆 小頂堆)

堆排序的思想這裡就先不講了,以後有時間再補上,下面是分別採用大頂堆和小頂堆實現的堆排序。注意 下面例子中排序的數字是。大頂堆方式 include include using namespace std 堆調整 將nums s.m 調整為大頂堆,其中除了nums s 之外均滿足大頂堆的定義 void ...