在100亿个数中找出最大的前k个数(海量数据Top k问题),100亿啊,怎么找都觉得占空间很大啊,按一个数四个字节算,那也得40g啊,那得用堆的方法来做。 如何建立一个堆戳链接
点击打开链接
首先把前k个数构建成一个小堆,这样第一个数a[0]永远是这前k个数中最小的,从第k个数开始,每一个数和a[0]做比较,如果比a[0]大的话,它们两个一换,然后再将这个堆重新调整成一个小堆,继续用a[0]和第k+1的数进行比较,以此类推,一直到这些数轮完,那么这个堆里的这k个数就是这100亿个数中最大的了(其中涉及到向下向上调整都在之前如何建立堆里,戳上面的链接)
void TopK(DataType* a, size_t n, size_t k)
{
int i;
MakeHeap(a, k);//小堆
for (i = k; i < n; ++i)
{
if (a[i]>a[0])
{
DataType tmp = a[0];
a[0] = a[i];
a[i] = tmp;
AdjustDown(a, k, 0);
}
}
for (i = 0; i < k; ++i)
{
printf("%d ", a[i]);
}
printf("\n");
}
优先队列是允许至少下列两种操作的数据结构:允许找出、返回和删除优先队列中最小的元素。下面是堆得实现
#define N 1000
typedef struct PriorityQueue
{
DataType _a[N];
size_t _size;
}PriorityQueue;
void PriorityQueueInit(PriorityQueue* q)//初始化
{
assert(q);
q->_size = 0;
memset(q->_a, 0, sizeof(DataType)*N);
}
void PriorityQueuePush(PriorityQueue* q, DataType x)//入队
{
assert(q);
if (q->_size >= N)
{
printf("PriorityQueue full\n");
return;
}
q->_a[q->_size++] = x;
AdjustUp(q->_a, q->_size, q->_size - 1);
}
void PriorityQueuePop(PriorityQueue* q)//出队
{
assert(q);
if (NULL == q)
{
printf("PriorityQueue empty\n");
return;
}
q->_a[0] = q->_a[q->_size - 1];
q->_size--;
AdjustDown(q->_a, q->_size, 0);
}
DataType PriorityQueueTop(PriorityQueue* q)//取栈顶元素
{
assert(q);
if (NULL == q)
{
printf("PriorityQueue empty\n");
return;
}
return q->_a[0];
}
size_t PriorityQueueSzie(PriorityQueue* q)//求队列元素个数
{
assert(q);
return q->_size;
}
size_t PriorityQueueEmpty(PriorityQueue* q)//求剩余元素个数
{
assert(q);
return q->_size;
}
如果有不对的地方,可以评论告诉我,望指导!