k-й наименьший элемент с использованием min-heap

Я решал проблему k-го наименьшего элемента с помощью min-heap, но застрял, поскольку он всегда дает мне первый наименьший элемент, поэтому я предполагаю, что моя функция extractmin работает неправильно. Мой подход заключался в том, чтобы превратить массив в структуру данных минимальной кучи в какой корень является минимальным элементом, а затем удалите k-1 наименьших элементов, а затем просто верните значение корня.

#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

person Hanoi    schedule 17.01.2019    source источник
comment
Звучит сложно. Почему бы просто не отсортировать и не вернуть k-й элемент? Кстати. int n; cin >> n; int arr[n]; не соответствует стандарту C ++.   -  person Swordfish    schedule 17.01.2019
comment
Решение ответа Госвина - сделать smallest индексом в массиве (то есть smallest = l(i) и smallest = r(i)), а затем сделать swap(arr[smallest], arr[i]).   -  person 0x499602D2    schedule 17.01.2019
comment
Ваш отладчик - бесценный инструмент. Используй это. Если не знаешь как, учись. В настоящее время. Это сэкономит вам огромное количество времени. Вы можете поблагодарить меня позже.   -  person Jim Mischel    schedule 17.01.2019


Ответы (1)


В 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 и друзья?

person Goswin von Brederlow    schedule 17.01.2019
comment
Тем не менее при вводе не удается: n = 5; Массив = 12 5 787 1 23; k = 2 Его правильный вывод: 5 И вывод вашего кода: 12 - person Hanoi; 17.01.2019