堆排序是一種選擇排序,時間複雜度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--
)
如果發生交換的話,再將孩子結點作為父結點,與它的孩子節點再作比較。直到葉子結點。
1.一開始,堆佔據整個陣列。取出堆頂元素,與堆尾元素交換。交換後,堆尾加入有序子陣列,堆長度-1。//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;
}
2.所有堆元素加入有序陣列後,排序完畢。
3.小頂堆用於降序排序,大頂堆用於公升序排序。
for
(let j = arr.end-
1; j >
0; j--
)
拿小頂堆舉例來說,堆頂就是當前k個中最小的。如果最大的前k個元素都在這個堆中,那堆頂就是第k大的那個元素。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個元素初始就行)
從arr[k](第k+1個元素)開始和堆頂作比較,如果大於堆頂就和堆頂交換;交換後,堆頂可能不是堆中最小元素,所以需要堆化。
不斷地有更大的元素被換入堆中,並且堆頂又能保持堆中最小。
當arr[length-1]也比較完成後,堆中就包含了最大的k個元素了,並且堆頂arr[0]就是第k大的元素。時間複雜度o(nlogk)
還有乙個演算法能用o(n)解決topk問題,之後在做研究!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)
}
參考:
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 ...