堆的top-k问题

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/CY071512/article/details/79381881

在大规模数据处理中,遇到的一类问题是,在海量数据中找出出现频率最高的前K个数,或者从海量数据中找出最大的前K个数,这类问题被称为“top K”问题。
堆的建立
解决top-k问题,可以用建堆方法来处理,选取最高或者最低的数据可以建立小堆来处理。
解决方案:
在海量数据中查找最大的前K个数,可以建立一个以K大小的小堆,小堆特点是堆顶(数组第一个元素)为当前堆结构的最小值,在海量数据中再次查找时,只和堆顶元素进行比较,大于则入堆,这样就能保证堆里元素永远是目前最大的前K个。

void AdjustDown(Datatype* a, size_t n, int root)//向下调整(小堆)
{
    int parent = root;
    int child = (root * 2 + 1);//左孩子
    while (child < n)
    {
        if (a[child] > a[child+1] && (child+1 < n))//比较左右孩子大小。取较小值
        {
            ++child;
        }
        if (a[parent] > a[child])
        {
            Datatype tmp = a[child];
            a[child] = a[parent];
            a[parent] = tmp;
            parent = child;
            child = parent * 2 + 1;
        }
        else
            break;
    }
}
void TopK(Datatype* a, size_t k, int n)//寻找前K个较大的数(建立小堆)
{
    MakeHeap(a, k);
    for (int i = k+1; i < n; i++)
    {
        if (a[i] > a[0])
        {
            a[0] = a[i];
            AdjustDown(a, k, 0);
        }
        else
            continue;
    }
}
void TestTopK()
{
    int a[1000] = { 0 };
    srand(time(0));
    int i = 0;
    for (i = 0; i < 1000; i++)
        a[i] = rand() % 10000;//产生0~10000的数字
    //规定数组里某些元素是超出10000的数字,若打印出来不是以下数字,则错误。
    a[525] = 10001;
    a[89] = 10002;
    a[0] = 10003;
    a[789] = 10004;
    a[23] = 10005;
    a[180] = 10006;
    a[999] = 10007;
    a[666] = 10008;
    a[483] = 10009;
    a[359] = 10010;
    TopK(a, 10, sizeof(a) / sizeof(a[0]));
    for (i = 0; i < 10; i++)
    {
        printf("%d ", a[i]);
    }
}

猜你喜欢

转载自blog.csdn.net/CY071512/article/details/79381881