Оптимизация структуры кучи для heapsort

121
9

Я использую heapsort, используя кучу. Для этого вставляются каждое значение для сортировки. Метод вставки вызывает heapifyUp() (aka siftUp), поэтому это означает, что каждый раз, когда вставляется другое значение, вызывается heapifyUp. Это самый эффективный способ?

Другая идея заключалась бы в том, чтобы вставить все элементы, а затем вызвать heapifyUp. Я думаю, heapifyUp нужно будет вызвать на каждом из них? Делает это так лучше?

спросил(а) 2016-08-18T13:50:00+03:00 4 года, 2 месяца назад
1
Решение
72

Вставка каждого элемента будет строить кучу в O (n log n) времени. То же самое, если вы добавляете все элементы в массив, а затем повторно вызываете heapifyUp().

Floyd Algorithm строит кучу снизу вверх в O (n) времени. Идея состоит в том, что вы берете массив, который в любом порядке и, начиная с середины, просеивает каждый элемент до его надлежащего места. Алгоритм:

for i = array.length/2 downto 0
{
siftDown(i)
}

Вы начинаете посередине, потому что последняя длина /2 элемента в массиве - это листья. Их нельзя отбросить. Работая с середины, вы уменьшаете количество предметов, которые нужно переместить.

Пример разницы

Пример ниже, превратив массив из 7 элементов в кучу, показывает разницу в объеме выполненной работы.

Метод heapifyUp()

[7,5,6,1,2,3,4]  (starting state)

Начните с конца и поместите пузырьки вверх.

Переместить 4 в нужное место

[7,5,4,1,2,3,6]
[4,5,7,1,2,3,6]

Переместить 3 на свое место

[4,5,3,1,2,7,6]
[3,5,4,1,2,7,6]

Переместить 2 на свое место

[3,2,4,1,5,7,6]
[2,3,4,1,5,7,6]

Переместить 1 на свое место

[2,1,4,3,5,7,6]
[1,2,4,3,5,7,6]

Теперь куча в порядке. Это потребовало 8 свопов, и вам все равно нужно проверить 4, 2 и 1.

Алгоритм Флойда

[7,5,6,1,2,3,4]  (starting state)

Начинайте с половины и просеивайте вниз. В массиве, состоящем из 0 элементов из 7 элементов, половина точки равна 3.

Переместить 1 на свое место

[7,5,6,1,2,3,4]  (no change. Remember, we're sifting down)

Переместить 6 на свое место

[7,5,3,1,2,6,4]

Переместить 5 на свое место

[7,1,3,5,2,6,4]
[7,1,3,4,2,6,5]

Переместить 7 на свое место

[1,7,3,5,2,6,4]
[1,2,3,5,7,6,4]

И все готово. Потребовалось 5 свопов, и нет ничего, что можно было бы проверить.

ответил(а) 2016-08-18T17:26:00+03:00 4 года, 2 месяца назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема