建立topK是基于堆排序变化而来的,我们建立topK是因为海量数据(正整数)按逆序排序排列的前k个数(topK),因为数据量太大,不能全部存放进内存中,我们只能存进一下部分,但是我现在就想找到前k个最小的数存进我们的空间之中,我们应该怎么办?
不建立堆的话,我们也是有办法的,可以先进行排序,我们再找到前k个元素存放进我们的空间中,但是我们这次用堆的形式来实现
我们来说一说思路(以小顶堆为例):1.我们用nums来存放数据,同时建立一个存放k个元素的容器heap来存放nums的前k个元素
2.我们将heap的元素建立一个大堆,建堆的过程在我的博客排序(上)详细的讲到过,然后我们将nums中k以后的元素和这个堆顶来比较,因为堆顶是这个堆中最大的元素,只要小于堆顶就有资格进入我们的堆,我们将堆顶和nums对应的元素交换
3.然后我们向下调整,更新堆,让最大的再次到达根节点的地方
#include<iostream>
#include<vector>
#include<string>
using namespace std;
//向下调整算法,建立一个小堆
void Swap(int* a, int* b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
vector<int> Ajustdown(vector<int>heap, int k, int pos)
{//建立一个大堆
int parent = pos;
int child = 2 * parent + 1;
while (child < k)
{
if (child+1<k && heap[child]<heap[child + 1])//找到孩子中较大的一个孩子
{
child = child + 1;
}
if (heap[parent] > heap[child])//和父节点比较哪个更大
{
break;
}
else {
Swap(&heap[parent], &heap[child]);//如果父亲比孩子要大,交换父节点和孩子的值
parent = child;
child = parent * 2 + 1;
}
}
return heap;
}
void creat_heap(vector<int>& heap, int k)
{//建立一个大堆
int parent = (k - 1 - 1) / 2;
for (int i = parent; i >= 0; i--)
{
heap = Ajustdown(heap, k, i);
}
}
int main()
{
int k = 5;//表示heap这个空间只能存放5个元素
vector<int>nums = { 12,52,78,59,46,49,65,42,15,34,28,9,5 };
vector<int>heap(k, 0);//给heap的空间进行初始化的操作
for (int i = 0; i < k; i++)//将nums数组中前个值存放到heap当中
{
heap[i] = nums[i];
}
creat_heap(heap, k);//建立一大堆
for (int i = 0; i < heap.size(); i++)//遍历我们建立好的堆
{
cout << heap[i] << " ";
}
cout << endl;
for (int i = k; i < nums.size(); i++)//因为我们建立的是大堆,根节点就是最大的一个数
{
if (nums[i] < heap[0])//找到一个比根节点小的,代替他
{
heap[0] = nums[i];
heap = Ajustdown(heap, k, 0);
}
}
for (int i = 0; i < heap.size(); i++)
{
cout << heap[i] << " ";
}
cout << endl;
system("pause");
}