【数据结构】topK问题,海量数据找出前K个大的数据

topK问题:

假如需要从十亿个数据中找出最大的前k个数,也就是海量数据处理问题。

一般遇见这种问题,我们肯定会想到先排序,再取前K个数据就可以了。但是海量数据如果这样处理,那就会大大提高时间复杂度了。那么我们应该如何处理呢?

首先假如这是一组大数据,取出前K个元素放入小堆里:

【数据结构】topK问题,海量数据找出前K个大的数据_第1张图片

在小堆里,这前K个元素是有序的,最小的元素放在堆顶。依次取数组里的下一个数据与堆顶元素进行比较,如果数组数据大于堆顶元素,就可以利用对结构来删除堆顶元素,删除后的堆结构仍然是有序的;然后将该数组数据利用堆结构放入堆中,此时堆结构仍是有序的。图解如下所示:

【数据结构】topK问题,海量数据找出前K个大的数据_第2张图片


程序源码:

堆结构的基本操作源码

test.c

#include"Heap.h"
#include"PriorityQueue.h"
#include
#include
#include
#define N 10
#define K 4
using namespace std;

//堆
void test(){
    int arr[] = { 53, 17, 78, 9, 45, 65, 87, 23 };
    Heap<int,Less<int>> hp(arr, sizeof(arr) / sizeof(arr[0]));
    hp.Push(80);
    hp.Pop();
    cout << hp.Size() << endl;
    cout << hp.Top() << endl;
    cout << hp.Back() << endl;
}

//优先级队列
void test2(){
    int arr[] = { 53, 17, 78, 9, 45, 65, 87, 23 };
    PriorityQueue<int> prq;
    for (size_t i = 0; i < sizeof(arr) / sizeof(arr[0]); ++i){
        prq.Push(arr[i]);
    }
    cout << prq.Top() << endl;
    cout << prq.Size() << endl;
    prq.Pop();
    cout << prq.Top() << endl;
    cout << prq.Size() << endl;
}

//TopK(海量数据处理问题)
void TopK(){
    int arr[N];
    int max[K];
    for (size_t i = 0; i < N; ++i){
        arr[i] = rand() % N;
    }
    for (size_t j = 0; j < K; ++j){
        max[j] = arr[j];
    }
    //前K个元素建一个小堆
    Heap<int, Less<int>> hp(max, sizeof(max) / sizeof(max[0]));
    //依次读取arr[]之后的数据,与小堆堆头元素比较,若该数据大于堆头元素,则删除堆头元素,将该数据放到堆里,堆会自己排好序
    for (size_t k = K; k < N; ++k){
        if (arr[k] > hp.Top()){
            hp.Pop();
            hp.Push(arr[k]);
        }
    }
    //依次输出最大的K个数据
    hp.Print();
}

int main(){
    //test();
    //test2();
    TopK();
    system("pause");
    return 0;
}

测试结果:

N=10,K=4时:

【数据结构】topK问题,海量数据找出前K个大的数据_第3张图片

【数据结构】topK问题,海量数据找出前K个大的数据_第4张图片


N=100,K=20 时:

随机产生的数组arr[100]部分数据展示:

【数据结构】topK问题,海量数据找出前K个大的数据_第5张图片

最大的前K个数据:

【数据结构】topK问题,海量数据找出前K个大的数据_第6张图片

【数据结构】topK问题,海量数据找出前K个大的数据_第7张图片

你可能感兴趣的:(数据结构)