сортировка кучей - какую кучу (мин/макс) использовать для сортировки по возрастанию и убыванию?

Я замечаю очень странную вещь.

После прохождения этой лекции, я реализовал некоторый код для сортировки кучей на C++.

Код ниже.

    template<typename T> void min_heapify(std::vector<T> &vec, int i, int size)
    {
        int left  = (2*i); //left child of a zero-indexed heap (array)
        int right = (2*i)+1; //right child.
        int min;

        min = ( (left<size) && (vec[left] < vec[i]) ) ? left : i;
        min = ( (right<size) && (vec[right] < vec[min]) ) ? right : min;

        if (min!= i)
        {
            swapper(vec[i],vec[min]);
            min_heapify(vec, min, size);
        }
    }
    template<typename T> void build_min_heap(std::vector<T> &vec, int size)
    {
        int i = size/2;
        while(i--)
        {
            min_heapify(vec, i, size);

        }
    }
    template<typename T> void heap_sort(std::vector<T> &vec, int size)
    {
        // build min heap
        build_min_heap(vec, size);
        // then extract min repeatedly.
        while(size>0)
        {
            size--;
            swapper(vec[0],vec[size]);
            min_heapify(vec,0,size);
        }
    }

   int main()
   {
        vector<int> v{14,-1,1000, -999, 3,2,5,10};
        heap_sort(v, v.size());

        return 0;
   }

Особенность заключается в том, что для меня имеет смысл, что - построить минимальную кучу - извлечь минимальную (или выполнить min-heapify в корне после создания минимальной кучи) должно привести к возрастающему порядку. Однако после выполнения этого кода и распечатки результирующего вектора я получаю:

1000 14 10 5 3 2 -1 -999 

пытаясь понять, что происходит, я изменил

min = ( (left<size) && (vec[left] < vec[i]) ) ? left : i;
min = ( (right<size) && (vec[right] < vec[min]) ) ? right : min;

to

min = ( (left<size) && (vec[left] > vec[i]) ) ? left : i;
min = ( (right<size) && (vec[right] > vec[min]) ) ? right : min;

что на самом деле заканчивается выбором большего (или максимального) из родительских и дочерних узлов, и результирующий вектор:

-999 -1 2 3 5 10 14 1000 

Я делаю что-то неправильно или мое понимание сортировки кучи/кучи неясно? Что мне здесь не хватает?


person Raaj    schedule 02.10.2016    source источник
comment
Ваше понимание использования кучи в heapsort может быть менее чем эффективным: значения обычно выбираются последними.   -  person greybeard    schedule 02.10.2016


Ответы (1)


Да, swapper(vec[0],vec[size]); - это извлечение. Вы извлекаете первый элемент в последний элемент вектора. Отсюда и получение обратного результата.

Минимальный элемент кучи равен vec[0]. Замена этого на последнюю позицию создаст порядок от максимального до минимального в этом векторе.

Если вы реализуете что-то вроде

result.push_back(heap.pop_min());

Вы получите ожидаемый заказ.

person Captain Giraffe    schedule 02.10.2016
comment
Предполагается, что вы извлекаете с помощью... (вставляя в результирующий вектор) -- А вы? Это звучит как ненужная работа, если вам нужна сортировка на месте. Вместо этого вам следует изменить свои ожидания относительно того, как должна работать сортировка кучей, и если вы хотите, чтобы результат был обратным, используйте обратное сравнение. - person Benjamin Lindley; 02.10.2016
comment
@BenjaminLindley Спасибо за комментарий. Я пересмотрю. - person Captain Giraffe; 02.10.2016
comment
@BenjaminLindley Привет, значит ли это, что я должен прибегнуть к использованию max-heapify, чтобы выполнить сортировку по возрастанию на месте? - person Raaj; 02.10.2016
comment
@CaptainGiraffe Ах! Конечно. Если я просто меняю местами, не вынимая его, они (минимальные элементы) сидят в массиве. Спасибо. - person Raaj; 02.10.2016
comment
@Raaj: Да, я так думаю. Это то же самое, что вы получили бы, если бы, например, использовали стандартные библиотечные функции make_heap, а затем sort_heap. make_heap по умолчанию создает максимальную кучу, а sort_heap сортирует эту кучу в порядке возрастания. - person Benjamin Lindley; 02.10.2016
comment
@BenjaminLindley Если бы я прибегнул к сортировке кучи на месте, это имело бы смысл. Спасибо! Для тех, кто зайдет и попытается разобраться, пожалуйста, прочтите - csl .mtu.edu/cs2321/www/newLectures/09_Inplace_Heap_Sort.html для получения дополнительных пояснений. - person Raaj; 02.10.2016