海量數據處理的 Top K算法(問題) 小頂堆實現


  問題描述:有N(N>>10000)個整數,求出其中的前K個最大的數。(稱作Top k或者Top 10)

  問題分析:由於(1)輸入的大量數據;(2)只要前K個,對整個輸入數據的保存和排序是相當的不可取的。

        可以利用數據結構的最小堆來處理該問題。

        最小堆如圖所示,對於每個非葉子節點的數值,一定不大於孩子節點的數值。這樣可用含有K個節點的最小堆來保存K個目前的最大值(當然根節點是其中的最小數值)。

      每次有數據輸入的時候可以先與根節點比較。若不大於根節點,則舍棄;否則用新數值替換根節點數值。並進行最小堆的調整。

  實現代碼以及說明:

#include<stdio.h>
int n;  ///數字個數,n很大(n>10000)
int dui[10];
#define K 10    ///Top K,K的取值

void create_dui();  ///建堆 void UpToDown(int);  ///從上到下調整 int main()
{
    int i;
    int tmp;
    while(scanf("%d",&n)!=EOF)
    {
        for(i=1;i<=K;i++) ///先輸入K個
            scanf("%d",&dui[i]);
        create_dui();  ///建小頂堆
        for(i=K+1;i<=n;i++)
        {
            scanf("%d",&tmp);
            if(tmp>dui[1])  ///只有大於根節點才處理
            {
                dui[1]=tmp;
                UpToDown(1);    ///向下調整堆
            }
        }
    }
    return 1;
}

void create_dui()
{
    int i;
    int pos=K/2;      ///從末尾數,第一個非葉節點的位置K/2
    for(i=pos;i>=1;i--)
        UpToDown(i);
}

void UpToDown(int i)
{
    int t1,t2,tmp,pos;
    t1=2*i; ///左孩子(存在的話)
    t2=t1+1;    ///右孩子(存在的話)
    if(t1>K)    ///無孩子節點
        return;
    else
    {
        if(t2>K)  ///只有左孩子
            pos=t1;
        else
            pos=dui[t1]>dui[t2]? t2:t1;

        if(dui[i]>dui[pos]) ///pos保存在子孩子中,數值較小者的位置
        {
            tmp=dui[i];dui[i]=dui[pos];dui[pos]=tmp;
            UpToDown(pos);
        }
    }
}

   由於僅僅保存了K個數據,有調整最小堆的時間復雜度為O(lnK),因此TOp K算法(問題)時間復雜度為O(nlnK).


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM