Top k问题
—1.找到n个数据中最大的k个数据(n>k)
—2.找n个数据中最小的k个数据(n>k)
思路分析
- 建小堆解决最大的k个数据
- 建大堆解决最小的k个数据
以最大k问题为例:建一个数据数量为k个的小堆,若数据大于小堆的堆顶数据,则将2者数据进行交换,然后在进行向下调整,
小堆的性质:小的数据在堆顶,大的数据在后面
原因:我们将数组的前k个数据用来建一个k大小的小堆,建好堆后,我们将数组里下标为k的数据与此时堆顶的数据进行比较,若下标为k的数据大,则进堆;否则,不进堆。(这里时因为我们建的是小堆),
如果下标为k的数据进堆了,此刻观察根节点的左右子树,发现左右子树是小堆,那么就满足了向下调整算法的要求,用向下调整算法来处理。处理后,该堆是小堆,其根节点又是该队里最小的。
完成上述处理后,我们在不断的将新的堆顶(根节点)的数据与数组后的数据进行比较,交换,调整。(这里每处理一次后,若插入的数据大,则堆里最小的数据被弄出去)
- 完成这些操作后,此时堆里的数据是数组里数据最大的前k个数据
代码实现
void AdjustDown(HPDataType* a, int n, int root)
{
int parent = root;//这是下标
int child = 2 * parent + 1;//这是左子树的下标
//这里先假设左子树是2个子树中最小的那个
while (child < n)
{
//当右子树才是最小的时候,进行调整,让child + 1赋给child
if (child + 1 < n && a[child] > a[child + 1])
{
//这里child+1<n,是为了防止出现数组越界,
// 因为出现这中情况是,已经没意义了
child = child + 1;
}
if (a[child] < a[parent])
{
swap(&a[child], &a[parent]);
parent = child;
child = 2 * parent + 1;
}
else
{
break;
}
}
}
HPDataType* getmaxnumbers(HPDataType* a, int arrsize, int k)
{
HPDataType* arr = (HPDataType*)malloc(sizeof(HPDataType) * arrsize);
for (int i = 0; i < k; i++);
{
arr[i] = a[i];
}
//建堆
int n = arrsize;
for (int j = (n - 1 - 1) / 2; j > 0; --j)
{
AdjustDown(arr, n, j);
}
for (int i = k; k < n; k++)
{
if (arr[0] < a[k])
{
arr[0] = arr[k];
AdjustDown(arr, k, 0);
}
}
}
727

被折叠的 条评论
为什么被折叠?



