日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

堆排序 海量数据求前N大的值

發(fā)布時間:2024/4/14 编程问答 51 豆豆
生活随笔 收集整理的這篇文章主要介紹了 堆排序 海量数据求前N大的值 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

最(大)小堆的性質(zhì)

(1)是一顆完全二叉樹,遵循完全二叉樹的所有性質(zhì)。

(2)父節(jié)點(diǎn)的鍵值(大于)小于等于子節(jié)點(diǎn)的鍵值

??

堆的存儲

一般都用數(shù)組來表示堆,i結(jié)點(diǎn)的父結(jié)點(diǎn)下標(biāo)就為(i – 1) / 2。它的左右子結(jié)點(diǎn)下標(biāo)分別為2 * i + 1和2 * i + 2。如第0個結(jié)點(diǎn)左右子結(jié)點(diǎn)下標(biāo)分別為1和2。

?海量數(shù)據(jù)前n大,并且n比較小,堆可以放入內(nèi)存

【基本原理及要點(diǎn)】
????????? 最大堆求前n小,最小堆求前n大。方法,比如求前n小,我們比較當(dāng)前元素與最大堆里的最大元素,如果它小于最大元素,則應(yīng)該替換那個最大元 素。這樣最后得到的n個元素就是最小的n個。適合大數(shù)據(jù)量,求前n小,n的大小比較小的情況,這樣可以掃描一遍即可得到所有的前n元素,效率很高。

【擴(kuò)展】
??????????雙堆,一個最大堆與一個最小堆結(jié)合,可以用來維護(hù)中位數(shù)。

建立堆

? ? ? ? /**
* 將建立堆的過程看作是每次向堆中插入一個數(shù)據(jù)
* 每次插入數(shù)據(jù)都是在插入堆的尾部,然后進(jìn)行堆調(diào)整
* 說明:每次調(diào)整的時候,只需要向上調(diào)整即可,由于每次調(diào)整之后的子節(jié)點(diǎn)的值總是大于父節(jié)點(diǎn)
* ? ? 當(dāng)前插入放入節(jié)點(diǎn)向上一層一層調(diào)整時,始終保持子堆依然是最小堆結(jié)構(gòu)
* ? ? 如 ? ? ?10
* ? ? ? ? ? ? / ? ? \
* ? ? ? ? ? 14 ? ? 17
* ? ? ? ? ?/ ? \ ? ? / ? \
* ? ? ? 18 ?15 20 ? 37
* ? ? ?插入節(jié)點(diǎn)13時,13為18的子節(jié)點(diǎn),需交換,此時13為父節(jié)點(diǎn),同時由于13小于14,再次交換
? ? ? ? ?* ? ? ?注意這里不要調(diào)整13的子樹的結(jié)構(gòu),因?yàn)?3的子樹都是向上調(diào)整子最小堆得來,因此13的子樹本身滿足最小堆結(jié)構(gòu)
*/
?java代碼實(shí)現(xiàn) void minHeapBuild(int[] num,int index){ //num[0,1..index-1]為已經(jīng)實(shí)現(xiàn)的最小堆,index為插入num[index]值,建立新的堆int length=num.length;if(length<=0)return;int p=parent(index); while(p>=0&&index!=0){if(num[index]>=num[p])break;else{//交換節(jié)點(diǎn)int tmp=num[index]; num[index]=num[p]; num[p]=tmp;//重定位當(dāng)前節(jié)點(diǎn)index=p;p=parent(index);}}}

堆的刪除

? ? ? ? ?/** 堆的刪除,每次都是刪除堆頂?shù)脑?#xff0c;刪除后對堆進(jìn)行調(diào)整* 具體做法是用堆尾部的元素代替堆頂元素,然后調(diào)整堆*/

java代碼實(shí)現(xiàn) void minHeapDelete(int[] num, int len){int length=num.length;if(len>=length||len==0)return;int p=0;int child=leftChild(p);num[p]=num[len-1];//堆尾元素置于堆頂while(child<len){//找到左右子節(jié)點(diǎn)的較小值if(child+1<len && num[child]>num[child+1])child+=1;if(num[p]<=num[child])break;else{//交換節(jié)點(diǎn)int tmp=num[child]; num[child]=num[p]; num[p]=tmp;//重定位當(dāng)前父節(jié)點(diǎn)p=child;child=leftChild(p);}}}
int parent(int i){return (i-1)/2;} int leftChild(int i){return 2*i+1;}
部分參考:http://blog.163.com/xychenbaihu@yeah/blog/static/132229655201351984231220/ ? ? ? ? ? ? ? ? ?http://blog.csdn.net/morewindows/article/details/6709644/

轉(zhuǎn)載于:https://www.cnblogs.com/wennian/p/5036912.html

總結(jié)

以上是生活随笔為你收集整理的堆排序 海量数据求前N大的值的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。