使用最小堆的第k个最小元素

时间:2019-01-17 13:48:48

标签: c++ heap min-heap

我正在使用min-heap解决第k个最小元素的问题,但由于总是给我第一个最小元素而卡住了,所以我猜我的extractmin函数不能正常工作,我的方法是将数组变成min堆数据结构,其中root是最小元素,然后删除k-1个最小元素,然后简单地返回root的值。

#include <iostream>

using namespace std;

void swap(int &x, int &y)
{
    int u = x;
    x = y;
    y = u;
}

int l(int p)
{
    return 2 * p + 1;
}

int r(int p)
{
    return 2 * p + 2;
}

void heapify(int arr[], int i, int n);

void makeheap(int arr[], int n)
{
    int last = n - 1;
    for (int i = (last - 1) / 2; i >= 0; i--)
    {
        heapify(arr, i, n);
    }
}

void heapify(int arr[], int i, int n)
{
int smallest = arr[i],y=0;
if (l(i) <= n - 1 && arr[l(i)] < arr[i])
{
    smallest = arr[l(i)];
}
if (r(i) <= n - 1 && arr[r(i)] < smallest)
{
    smallest = arr[r(i)];
 y=1;
}
if (smallest != arr[i])
{ 
    if(y==0){
    swap(arr[l(i)], arr[i]);}
    else if(y==1)
    {
        swap(arr[r(i)],arr[i]);
    }
    heapify(arr, i, n);
}
}

void extractmin(int arr[], int &n)
{
    swap(arr[0], arr[n - 1]);
    n--;
    heapify(arr, 0, n);
}

int getmin(int arr[])
{
    return arr[0];
}

int main()
{
    int T;
    cin >> T;
    while (T--)
    {
        int n;
        cin >> n;
        int arr[n];
        for (int i = 0; i < n; i++)
        {
            cin >> arr[i];
        }
        int k;
        cin >> k;
        makeheap(arr, n);
        for (int i = 0; i < k - 1; i++) {
            extractmin(arr, n);
        }

        cout << getmin(arr) << "\n";
    }
}

输入:

2
6
7 10 4 3 20 15
3
5

7 10 4 20 15
4

预期输出:

7
15

我的输出:

3
4

1 个答案:

答案 0 :(得分:0)

在heapify()中使用

swap(smallest,arr[i]);

交换最小值和arr [i]中的值。但是arr [l(i)]或arr [r(i)]不变。这实际上是将arr [l(i)]和arr [r(i)]的较小值复制到arr [i]。

主要是你

for (int i = 0; i < k - 1; i--) {

将i递减计数直到达到INT_MIN而不是递增k。这很快导致堆为空,并且代码出现段错误。

PS:为什么不使用std :: make_heap和朋友?