Алгоритм Heapsort с использованием min-heap

Когда я реализую heapsort используя min-heap сортирует массив от наибольшего к наименьшему. Это желаемый результат для heapsort с помощью min-heap? Кажется излишним сортировать снова, чтобы вывести от наименьшего к наибольшему после завершения сортировки, так как heap сама имеет наименьшую по величине структуру.

КОД:

#include <iostream>
#include <vector>
#include "random.h"#include "print.h"int parent(int i)
{
return (i - 1) / 2;
}
int left(int i)
{
if(i == 0)
return 1;
else
return 2*i;
}
int right(int i)
{   if(i == 0)
return 2;
else
return 2*i + 1;
}
void min_heapify(std::vector<int> &A, int i, int heapsize)
{
int smallest;
int l = left(i);
//std::cout << "left = " << l << std::endl;
int r = right(i);
//std::cout << "right = " << r << std::endl;
if(l <= heapsize && A[l] < A[i])
smallest = l;
else
smallest = i;
//std::cout << "smallest = " << smallest << std::endl;
if(r <= heapsize && A[r] < A[smallest])
smallest = r;
if(smallest != i) {
print(A);
exchange(A, i, smallest);
min_heapify(A, smallest, heapsize);
}
}
void build_min_heap(std::vector<int> &A)
{
int heapsize = A.size() - 1;
for(int i = (A.size() - 1) / 2; i >= 0; i--)
min_heapify(A, i, heapsize);
}
void heapsort(std::vector<int> &A)
{
int heapsize = A.size() - 1;
build_min_heap(A);
std::cout << "heapsort after buildmaxheap" << std::endl;
print(A);
for(int i = A.size() - 1; i > 0; i--) {
exchange(A, 0, i);
heapsize--;
std::cout << "heapsize = " << heapsize << std::endl;
min_heapify(A, 0, heapsize);
}
}
int main()
{
std::vector<int> B;
fill(B, 5);
print(B);
heapsort(B);
print(B);
return 0;
}

Вывод из кода:

41 65 31 41 19
41 65 31 41 19
41 65 19 41 31
41 19 65 41 31
41 19 31 41 65
19 41 31 41 65
heapsort after buildmaxheap
19 31 41 41 65
heapsize = 3
65 31 41 41 19
31 65 41 41 19
heapsize = 2
heapsize = 1
65 41 41 31 19
heapsize = 0
65 41 41 31 19

Выход на 20 элементов:

41 65 31 41 19 15 72 11 78 69 37 23 29 63 75 4 5 49 75 99
after buildmaxheap
4 5 15 11 19 23 29 41 31 69 37 41 72 63 75 65 78 49 75 99
after sort
99 78 75 75 72 69 65 63 49 41 41 37 31 29 23 19 15 11 5 4

4

Решение

порядок: Используйте max-heapify для сортировки в порядке возрастания, min-heapify для сортировки в порядке убывания.

Сортировка: Сборка кучи с помощью min-heapify не сортирует ваш массив; это только усиливает (более слабое) свойство минимальной кучи, то есть

A[parent(i)] <= A[i]

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

Код, который вы публикуете, сразу выглядит правильно, но не компилируется как есть, поэтому я не могу проверить. Если ваш массив выглядит отсортированным сразу после построения кучи, это должно быть совпадением. Попробуйте больший тест.

2

Другие решения

Мне просто интересно об этой самой проблеме (разве в сортировке кучи нет лишнего шага в конце, ненужной замены элементов. Просто используйте min-heaps и позвольте call min-heapify и сделай свою работу).

Что касается этого способа, мы могли бы достичь времени O (logn), что несколько дисквалифицирует модель дерева двоичных решений — которая говорит, что O (nlogn) является приемлемой самой жесткой верхней границей для алгоритмов сортировки сравнения.

Краткий ответ: структура данных кучи не является деревьями двоичного поиска. Куча может гарантировать порядок элементов в порядке сверху вниз, но бинарное дерево поиска гарантирует, что они также будут упорядочены слева направо. Мы просто смешивали бинарные деревья и кучи.

Мин куча только гарантирует,

Amin[Parent]<=A[either_of_the_children] // says nothing about ordering of children

Вот двоичное дерево (хотя и не сбалансированное и не отсортированное):

Бинарное дерево

А вот и куча:

мин куча

Надеюсь, вы поняли мою точку зрения. Если все еще нет, то представьте, что минимальная куча представляет массив, гарантирующий, что parent меньше своего потомка, но ничего не говорит о том, все ли потомки расположены в отсортированном порядке слева направо?
Мы по-прежнему будем выполнять мини-heapify для каждого дочернего элемента текущего корневого каталога, подлежащего обмену.

1

Обычно вы используете максимальную кучу для сортировки в порядке возрастания, потому что это проще.
Используя max-heap, вы «плаваете» max вперед, и строите отсортированный список сзади.

Если вы хотите использовать минимальную кучу для сортировки в порядке возрастания, вы должны построить ее в обратном порядке. (т.е. низший это последний индекс ). В противном случае вы будете сбивать свою кучу.

start 18 70 6 13 12 55
min-heap(backwards) -> 18 70 55 13 12 6
then
swap  6 w 18 -> 6, 70 55 13 12 18 -> sink 18 -> 70 55 13 18 12
swap 12 w 70 -> 6 12, 55 13 18 70 -> sink 70 -> 55 70 18 13
swap 13 w 55 -> 6 12 13, 70 18 55 -> sink 55 -> 70 55 18
swap 18 w 70 -> 6 12 13 18, 55 70 -> sink 70 -> 70 55
swap 55 w 70 -> 6 12 13 18 55, 70
done
0
По вопросам рекламы [email protected]