Почему не сложность построения двоичной кучи путем вставки O (n) во времени?

Фон

Согласно Википедии и другим источникам, которые я нашел, создание двоичной кучи n элементов, начиная с пустой двоичной кучи и вставляя в нее элементы n, составляют O (n log n), поскольку вставка двоичной кучи выполняется за O (log n), и вы делаете это n раз. Назовем это алгоритмом вставки.

Он также представляет альтернативный подход, в котором вы опускаете / просачиваете / просачиваете вниз / каскадируете / накапливаете вниз / пузыри вниз первую / верхнюю половину элементов, начиная со среднего элемента и заканчивая первым элементом, и что это O (n), гораздо лучшая сложность. Доказательство этой сложности основывается на понимании того, что сложность приемника для каждого элемента зависит от его высоты в двоичной куче: если он находится внизу, он будет маленьким, возможно, нулевым; если он рядом с верхом, он может быть большим, может быть, n. Дело в том, что сложность не log n для каждого элемента, погруженного в этот процесс, поэтому общая сложность намного меньше, чем O (n log n < / em>), и на самом деле это O (n). Назовем это алгоритмом стока.

Вопрос

Почему по тем же причинам сложность алгоритма вставки не такая же, как у алгоритма приемника?

Рассмотрим фактическую работу, проделанную для первых нескольких элементов в алгоритме вставки. Стоимость первой вставки не log n, она равна нулю, потому что двоичная куча пуста! Стоимость второй вставки в худшем случае равна одному свопу, а стоимость четвертого - в худшем случае двум свопам и так далее. Фактическая сложность вставки элемента зависит от текущей глубины двоичной кучи, поэтому сложность для большинства вставок меньше O (log n). Стоимость вставки даже технически не достигает O (log n) до тех пор, пока после не будут вставлены все n элементов [это O (log (< em> n - 1)) для последнего элемента]!

Эта экономия звучит так же, как экономия, полученная алгоритмом приемника, так почему же они не учитываются одинаково для обоих алгоритмов?


person indil    schedule 20.01.2013    source источник
comment
Ваша логика мне кажется вполне разумной.   -  person Jerry Coffin    schedule 20.01.2013
comment
@indil, поскольку нотация big-O используется для асимптотической временной сложности наихудшего случая, вы должны рассмотреть самый дорогой сценарий вставки, который будет строить max-heap из списка из n элементов даны в порядке возрастания. Будет O (n / 2) из ​​них, добавленных в позиции листьев, и каждый из них будет расширен на всю высоту кучи, то есть O (log n). Таким образом, в худшем случае это дает O (n * log (n)).   -  person 808sound    schedule 20.01.2013
comment
Как писал @ 808sound, страница Википедии неявно предполагает проверку наихудшего случая.   -  person Michael Foukarakis    schedule 20.01.2013
comment
Я не следую математике из статьи Википедии о сложности. Я придумываю Sum [d = 0 to floor (log2 n)] of 2 ^ d * (floor (log2 n) - d) для количества перестановок (худший случай) для идеального двоичного дерева высотой / глубиной d ( с нуля), и я не вижу, как уменьшить это до O (n). Но я не лучший в этой математике. Если бы я мог это понять, я бы понял, как получить O (n) на бумаге. Однако я также написал код для вышеуказанного суммирования и сам наблюдал за сложностью O (n) в числах, так что вот она.   -  person indil    schedule 04.02.2013
comment
Спасибо всем за комментарии и ответы!   -  person indil    schedule 04.02.2013
comment
Аналогично: сложность сборки-кучи   -  person nawfal    schedule 05.06.2014


Ответы (4)


Интуиция заключается в том, что алгоритм приемника перемещает только несколько вещей (те, что находятся в маленьких слоях наверху кучи / дерева) на расстояние log (n), в то время как алгоритм вставки перемещает многие вещи (те, что в больших слоях внизу куча) расстояние log (n).

Интуиция относительно почему алгоритма приемника может уйти от этого, что алгоритм вставки также отвечает дополнительному (приятному) требованию: если мы остановим вставку в любой момент, частично сформированная куча должна быть ( и есть) допустимая куча. Для алгоритма приемника все, что мы получаем, - это странная искаженная нижняя часть кучи. Что-то вроде сосны со срезанной верхушкой.

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

person Andrew W.    schedule 22.01.2013

Фактически, когда n = 2 ^ x - 1 (самый низкий уровень заполнен), n / 2 элемента могут потребовать log (n) свопов в алгоритме вставки (чтобы стать листовыми узлами). Таким образом, вам понадобится (n / 2) (log (n)) свопов только для листьев, что уже делает его O (nlogn).

В другом алгоритме только один элемент требует обмена log (n), 2 требует обмена log (n) -1, 4 требует обмена log (n) -2 и т. Д. Википедия показывает доказательство того, что это приводит к серии, сходящейся к константа вместо логарифма.

person Maciej Stachowski    schedule 20.01.2013

Хотя верно, что log (n-1) меньше, чем log (n), он не меньше настолько, чтобы иметь значение.

Математически: наихудшая стоимость вставки i-го элемента равна ceil (log i). Следовательно, в наихудшем случае стоимость вставки элементов с 1 по n равна sum (i = 1..n, ceil (log i))> sum (i = 1..n, log i) = log 1 + log 1 + .. . + журнал N = журнал (1 × 2 × ... × N) = журнал N! = O (п войти п).

person Raymond Chen    schedule 21.01.2013

Вчера столкнулся с той же проблемой. Я попытался придумать какое-нибудь доказательство, чтобы удовлетворить себя. Есть ли в этом смысл?

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

Наихудшее время работы для уровня выше листьев:

к * (n / 2 h) * h

где h - высота (листья равны 0, вершина - log (n)), k - константа (для удобства). Итак (n / 2 h) - это количество узлов на уровне, а h - МАКСИМАЛЬНОЕ количество операций «погружения» на вставку.

Есть log (n) уровней, следовательно, общее время работы будет

Сумма для h от 1 до log (n): n * k * (h / 2 h)

Это k * n * SUM h = [1, log (n)]: (h / 2 h)

Сумма представляет собой простую арифметико-геометрическую прогрессию, которая дает 2. Таким образом, вы получаете время работы k * n * 2, что составляет O (n).

Время прохождения уровня не совсем то, что я сказал, но оно строго меньше. Есть ли подводные камни?

person 2bigpigs    schedule 24.07.2014