Куча против двоичного дерева поиска (BST)

В чем разница между кучей и BST?

Когда использовать кучу, а когда использовать BST?

Если вы хотите получить элементы в отсортированном виде, лучше ли BST по сравнению с кучей?


person kc3    schedule 27.05.2011    source источник
comment
Этот вопрос кажется не по теме, потому что он касается информатики и его следует задавать на cs.stackexchange.com.   -  person Flow    schedule 14.09.2013
comment
@Flow его спросили по адресу: cs.stackexchange.com/questions/27860/   -  person Ciro Santilli 新疆再教育营六四事件ۍ    schedule 09.04.2015
comment
Я чувствую, что это относится как к обмену стеками, так и к переполнению стека. Так что иметь это здесь нормально   -  person Azizbro    schedule 12.05.2019


Ответы (8)


Резюме

          Type      BST (*)   Heap
Insert    average   log(n)    1
Insert    worst     log(n)    log(n) or n (***)
Find any  worst     log(n)    n
Find max  worst     1 (**)    1
Create    worst     n log(n)  n
Delete    worst     log(n)    log(n)

Все средние значения времени в этой таблице такие же, как и их худшие времена, за исключением вставки.

  • *: везде в этом ответе BST == Balanced BST, поскольку несбалансированный отстой асимптотически
  • **: используя тривиальную модификацию, описанную в этом ответе
  • ***: log(n) для кучи дерева указателей, n для кучи динамического массива

Преимущества двоичной кучи над BST

Преимущество BST перед двоичной кучей

  • поиск произвольных элементов - O(log(n)). Это потрясающая особенность BST.

    Для кучи это обычно O(n), за исключением самого большого элемента, который равен O(1).

Ложное преимущество кучи над BST

  • куча O(1), чтобы найти макс, BST O(log(n)).

    Это распространенное заблуждение, потому что тривиально изменить BST, чтобы отслеживать самый большой элемент, и обновлять его всякий раз, когда этот элемент может быть изменен: при вставке более крупного свопа при удалении найдите второй по величине. Можно ли использовать двоичное дерево поиска для имитации работы кучи? (упомянуто Йео).

    Фактически, это ограничение кучи по сравнению с BST: единственный эффективный поиск - это поиск самого большого элемента.

Среднее значение вставки двоичной кучи O(1)

Источники:

Интуитивный аргумент:

  • нижние уровни дерева имеют экспоненциально больше элементов, чем верхние уровни, поэтому новые элементы почти наверняка будут располагаться внизу
  • вставка кучи начинается снизу, BST должна начинаться сверху

В двоичной куче увеличение значения данного индекса также равно 18_ по той же причине. Но если вы хотите это сделать, вполне вероятно, что вы захотите обновлять дополнительный индекс по операциям с кучей Как реализовать операцию уменьшения ключа O (logn) для приоритетной очереди на основе min-heap? например, для Дейкстры. Возможно без дополнительных затрат времени.

Тест вставки стандартной библиотеки GCC C ++ на реальном оборудовании

Я протестировал C ++ std::set (Красно-черное дерево BST) и std::priority_queue (куча динамического массива), чтобы проверить, прав ли я насчет времени вставки, и вот что у меня получилось:

введите описание изображения здесь

  • введите описание изображения здесь

    Интерпретация:

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

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

    • TODO Я не могу полностью интерпретировать BST, поскольку он не выглядит таким логарифмическим и несколько более постоянным.

      Однако с этой более подробной информацией мы можем видеть несколько отдельных линий, но я не уверен, что они представляют: я ожидал, что нижняя линия будет тоньше, поскольку мы вставляем верхнюю нижнюю?

    Проверено с помощью этой person Ciro Santilli 新疆再教育营六四事件ۍ    schedule 09.04.2015

comment
Я + 1ed, но документ, оправдывающий среднюю вставку двоичной кучи O (1), теперь является мертвой ссылкой, а на слайдах просто утверждается утверждение без доказательства. Также я думаю, что это поможет прояснить, что средний случай здесь означает среднее при условии, что вставленные значения происходят из некоторого конкретного распределения, поэтому я не уверен, насколько убийственна эта функция на самом деле. - person j_random_hacker; 16.09.2016
comment
BST и сбалансированный BST, по-видимому, взаимозаменяемы. Следует пояснить, что ответ относится к сбалансированному BST, чтобы избежать путаницы. - person gkalpak; 18.01.2018
comment
А как насчет максимальной добычи? В очереди с приоритетом мы также хотели бы извлечь максимум. Разве это не было бы log (n)? - person flow2k; 07.08.2018
comment
@flow2k как для max, так и для min, это тривиально для BST с упомянутой модификацией, а для кучи, я думаю, вам просто нужно сохранить две кучи, отсортированные по-разному для O(1). - person Ciro Santilli 新疆再教育营六四事件ۍ 07.08.2018
comment
Я больше подумаю о случае с BST - спасибо. Но для кучи я не понимаю, чтобы две кучи были отсортированы. Разве не одна куча? А куча не сортируется? - person flow2k; 07.08.2018
comment
@flow2k, если вы хотите как max, так и min, я имею в виду. Под сортировкой я подразумеваю инвертирование функции сравнения вставок. - person Ciro Santilli 新疆再教育营六四事件ۍ 07.08.2018
comment
@flow2k Куча не сортируется, и в этом ее главное отличие от BST! Вместо этого вы знаете только то, что каждый родитель выше (или ниже), чем дети. Можно рассматривать это как семью, где каждый родитель старше детей, но никаких других ограничений нет. Таким образом, гарантировано, что корень является самым старым в семье, но не более того. Итак, если вам нужно найти самого молодого человека в семье, вам нужно просканировать всю кучу. Или, в качестве альтернативы, поддерживайте вторую кучу с противоположным оператором сравнения, то есть одну кучу, где каждый родитель ›дочерний элемент, и другую кучу, где каждый родительский элемент‹ дочерние элементы. - person Bulat; 09.08.2018
comment
Что происходит, когда нужно удалить элемент min / max? В куче мы можем найти его за O (1), но тогда нам нужно будет сбалансировать его за O (n). Какой здесь лучше? - person Varun Garg; 14.08.2018
comment
@VarunGarg нет, удаление кучи - O (log (n)). Отредактировал ответ, просмотрите алгоритм удаления. Но это будет проблемой, если вы выполняете одно удаление для каждой вставки, в этом случае вы также можете использовать BST. - person Ciro Santilli 新疆再教育营六四事件ۍ 19.08.2018
comment
Благодарим за обновление ссылки о средней сложности. При быстром просмотре, кажется, что они обрабатывают 2 разных типа: равномерно случайное распределение в кучах и распределение в кучах, возникающее в результате вставки в кучу элементов из равномерно случайно распределенной перестановки 1, ..., n. Что интересно, это совершенно разные дистрибутивы! - person j_random_hacker; 11.12.2018
comment
@j_random_hacker, если вы углубитесь в подробности, возможно, отредактируйте непосредственно в средней двоичной кучу, вставьте или добавьте новый ответ, например мы также можем процитировать что-то более точное по статье или добавить полное доказательство. Мы также можем расширить график эксперимента, чтобы показать различия в поведении на практике. - person Ciro Santilli 新疆再教育营六四事件ۍ 11.12.2018
comment
@CiroSantilli 新疆 改造 中心 六四 事件 法轮功: Я не понимаю, почему операция удаления двоичной кучи равна O (log n). Это работает, только если у вас есть указатель на элемент в куче, но в большинстве случаев у вас есть ключ, и вам нужно сначала найти элемент, который принимает O (n). - person Ricola; 16.01.2019
comment
@Ricola да, удаление в куче относится только к корневому удалению, что немного вводит в заблуждение, поскольку оно находится в той же строке, что и BST. С другой стороны, можно считать, что удаление чего-либо в первую очередь подразумевает его поиск, и что стоимость поиска рассчитывается отдельно от стоимости удаления. - person Ciro Santilli 新疆再教育营六四事件ۍ 16.01.2019
comment
вставка кучи - это журнал (n), а не o (1) - person Bobo; 26.01.2019
comment
@Bobo Согласно моим исследованиям и экспериментам, это средний показатель o1. - person Ciro Santilli 新疆再教育营六四事件ۍ 26.01.2019
comment
@CiroSantilli 新疆 改造 中心 六四 事件 法轮功 интересно. можешь поделиться своими экспериментами и их результатами? - person Bobo; 02.02.2019
comment
@Bobo см. Графики в ответе в разделе Тест вставки стандартной библиотеки GCC C ++ на реальном оборудовании. Дайте мне знать, если вы обнаружите что-то не так с моими методами :-) - person Ciro Santilli 新疆再教育营六四事件ۍ 03.02.2019
comment
@MROB спасибо за комментарий. У вас есть ссылка на него? Я видел ссылки, в которых говорилось о средних границах, но не о самой вставке. - person Ciro Santilli 新疆再教育营六四事件ۍ 28.09.2019
comment
@Ciro Santilli 新疆 改造 中心 法轮功 六四 事件 вы можете увидеть доказательство в оригинальной статье: Haeupler, Bernhard; Сен, Сиддхартха; Тарьян, Роберт Э. (2015), Рангово-сбалансированные деревья (PDF), Транзакции ACM по алгоритмам, 11 (4): Ст. 30, 26, DOI: 10.1145 / 2689412, MR 336121 - person MROB; 30.09.2019
comment
@MROB большое спасибо. Я быстро поискал статью citeseerx. ist.psu.edu/viewdoc/, но я смог найти только автора, упоминающего ребалансировку и границы поворота после вставки. Можете ли вы дать точную цитату по самой амортизированной вставке из статьи? Или какая-то ссылка / аргумент, объясняющий, что эта граница подразумевает привязку вставки? В частности, по моей наивной интуиции, средняя вставка должна пройти через дерево выбора с логарифмической (N) глубиной. Извините, если это очевидно, но у меня нет времени на это исследовать. - person Ciro Santilli 新疆再教育营六四事件ۍ 30.09.2019
comment
@Ciro Santilli 新疆 改造 中心 法轮功 六四 事件 вы правы! Я имел в виду процесс ребалансировки. Я удалил свой исходный комментарий. Вставка такая же, как в AVL, которая занимает O (logn) - person MROB; 01.10.2019
comment
@MROB, спасибо за подтверждение! В любом случае, это заставило немного узнать о WAVL, поэтому я добавил новый заголовок заглушки к вопросу об этом. - person Ciro Santilli 新疆再教育营六四事件ۍ 01.10.2019
comment
Я думаю, что операция «find» может быть O (1) вместо O (n) для кучи, если мы создадим вспомогательный словарь, который сопоставляет значения с позициями в куче и соответственно обновляет словарь для любой операции. - person Hanhan Li; 28.02.2020
comment
@ user3320467 да, это должно работать. У него есть обратная сторона: скорость вставок будет ограничиваться хэш-картой (также O (1), но медленнее, чем куча, как показано в тесте). - person Ciro Santilli 新疆再教育营六四事件ۍ 28.02.2020
comment
В какой-то момент вы говорите, что двусвязные списки ограничивают ваши возможности вставки либо головой, либо хвостом, но это не совсем так. Вы можете вставить где угодно за линейное время. - person Yordan Grigorov; 24.03.2021
comment
@YordanGrigorov да, я имел в виду изолированную операцию, когда у вас нет промежуточного указателя, теперь поясняется подробнее - person Ciro Santilli 新疆再教育营六四事件ۍ 24.03.2021

Куча просто гарантирует, что элементы на более высоких уровнях больше (для max-heap) или меньше (для min-heap), чем элементы на более низких уровнях, тогда как BST гарантирует порядок (от «левого» к «правому»). Если вам нужны отсортированные элементы, используйте BST.

person Dante May Code    schedule 27.05.2011
comment
Куча просто гарантирует, что элементы на более высоких уровнях больше (для max-heap) или меньше (для min-heap), чем элементы на более низких уровнях,… - куча не обеспечивает этого для каждого уровня level, а только в родительско-дочерних цепочках. [1, 5, 9, 7, 15, 10, 11] представляет допустимую минимальную кучу, но 7 на уровне 3 меньше, чем 9 на уровне 2. Для визуализации см., Например, элементы 25 и 19 в образце изображения из Википедии для кучи. (Также обратите внимание, что отношения неравенства между элементами не являются строгими, поскольку элементы не обязательно уникальны.) - person Daniel Andersson; 23.08.2015
comment
Извините за опоздание, но я просто хочу внести ясность. Если двоичная куча отсортирована, то худшим случаем для поиска будет log n right. Таким образом, в этом случае двоичные кучи сортируются лучше, чем двоичные деревья поиска (красно-черный BST). Спасибо - person Krishna; 23.10.2017

Когда использовать кучу, а когда использовать BST

Куча лучше подходит для findMin / findMax (O(1)), тогда как BST хорош для всех находок (O(logN)). Вставка O(logN) для обеих структур. Если вас интересует только findMin / findMax (например, связанный с приоритетом), используйте кучу. Если вы хотите, чтобы все было отсортировано, используйте BST.

Первые несколько слайдов из здесь очень ясно объясняют вещи.

person xysun    schedule 04.07.2013
comment
Хотя в худшем случае вставка является логарифмической для обоих, средняя вставка кучи занимает постоянное время. (Поскольку большинство существующих элементов находятся внизу, в большинстве случаев новый элемент должен будет подняться только на один или два уровня, если вообще будет.) - person johncip; 27.04.2014
comment
@xysun Я думаю, что BST лучше в findMin и findMax stackoverflow.com/a/27074221/764592 - person Yeo; 22.11.2014
comment
@Yeo: Куча лучше для findMin xor findMax. Если вам нужны оба, то лучше BST. - person Mooing Duck; 10.04.2015
comment
Я думаю, это просто распространенное заблуждение. Бинарное дерево можно легко изменить, чтобы найти минимальное и максимальное значение, указанное Йео. На самом деле это ограничение кучи: единственный эффективный поиск - это минимум или максимум. Истинным преимуществом кучи является средняя вставка O (1), как я объясняю: stackoverflow.com/a/ 29548834/895245 - person Ciro Santilli 新疆再教育营六四事件ۍ 20.06.2015
comment
Используйте кучу, если вы ожидаете большого количества удалений, потому что это может разбалансировать высоту дерева и стать √N вместо ln N, Кроме того, если ваши данные не упорядочены случайным образом - person goonerify; 10.12.2015
comment
Ответ Чиро Сантилли намного лучше: stackoverflow.com/a/29548834/2873507 - person Vic Seedoubleyew; 17.06.2016
comment
по FAAAAR это лучший ответ - person user1735921; 07.02.2021

Как упоминалось другими, Heap может выполнять findMin или findMax в O (1), но не оба в одной структуре данных. Однако я не согласен с тем, что Heap лучше в findMin / findMax. Фактически, с небольшими изменениями, BST может выполнять оба findMin и findMax в O (1).

В этом модифицированном BST вы отслеживаете минимальный и максимальный узел каждый раз, когда выполняете операцию, которая потенциально может изменить структуру данных. Например, в операции вставки вы можете проверить, больше ли минимальное значение, чем вновь вставленное значение, а затем присвоить минимальное значение вновь добавленному узлу. Тот же метод можно применить к максимальному значению. Следовательно, этот BST содержит эту информацию, которую вы можете получить за O (1). (то же, что и двоичная куча)

В этом BST (сбалансированный BST), когда вы pop min или pop max, следующее минимальное значение, которое должно быть присвоено, является преемником минимального узла, тогда как следующее максимальное значение, которое должно быть назначено, является предшественником максимального узла. Таким образом, он выполняется за O (1). Однако нам нужно повторно сбалансировать дерево, поэтому оно все равно будет работать O (log n). (то же, что и двоичная куча)

Мне было бы интересно услышать вашу мысль в комментарии ниже. Спасибо :)

Обновлять

Перекрестная ссылка на аналогичный вопрос Можно ли использовать двоичное дерево поиска для имитации работы кучи? для более подробного обсуждения моделирования кучи с помощью BST.

person Yeo    schedule 22.11.2014
comment
Почему вы не согласны? не могли бы вы поделиться своей мыслью ниже? - person Yeo; 22.11.2014
comment
Вы, конечно, могли бы сохранить максимальное и / или минимальное значение BST, но что произойдет, если вы захотите его выдать? Вам нужно выполнить поиск в дереве, чтобы удалить его, а затем снова найти новый max / min, оба из которых являются операциями O (log n). Тот же порядок, что и вставки и удаления в куче приоритета, с худшей константой. - person user2752467; 22.11.2014
comment
@JustinLardinois Извините, я забыл выделить это в своем ответе. В BST, когда вы делаете pop min, следующее значение min, которое нужно назначить, является преемником узла min. и если вы выберете максимальное значение, следующее максимальное значение, которое будет назначено, будет предшественником максимального узла. Таким образом, он все еще выполняется в O (1). - person Yeo; 22.11.2014
comment
Исправление: для popMin или popMax это не O (1), а O (log n), потому что это должен быть сбалансированный BST, который необходимо повторно балансировать при каждой операции удаления. Следовательно, это то же самое, что и двоичная куча popMin или popMax, которая запускает O (log n) - person Yeo; 22.11.2014
comment
Вы можете получить первое значение min / max, но получение kth min / max вернется к нормальной сложности BST. - person Chaos; 09.03.2015

Бинарное дерево поиска использует определение: для каждого узла узел слева от него имеет меньшее значение (ключ), а узел справа от него имеет большее значение (ключ).

Где в качестве кучи, будучи реализацией двоичного дерева, используется следующее определение:

Если A и B - узлы, где B - дочерний узел A, тогда значение (ключ) A должно быть больше или равно значению (ключу) B. То есть ключ (A) ≥ key (B ).

http://wiki.answers.com/Q/Difference_between_binary_search_tree_and_heap_tree

Сегодня я задавал тот же вопрос на экзамене, и я понял его правильно. улыбка ... :)

person Shin Kazama    schedule 25.06.2013
comment
куча, являющаяся реализацией двоичного дерева - просто указание на то, что куча - это своего рода двоичное дерево, а не вид BST - person foamroll; 15.05.2015

Другое использование BST вместо кучи; из-за важной разницы:

  • поиск преемника и предшественника в BST займет время O (h). (O (logn) в сбалансированном BST)
  • в то время как в куче, потребуется O (n) времени, чтобы найти преемника или предшественника некоторого элемента.

Использование BST в куче. Допустим, мы используем структуру данных для хранения времени посадки рейсов. Мы не можем запланировать рейс на посадку, если разница во времени посадки меньше "d". И предположим, что многие рейсы запланированы для приземления в структуре данных (BST или Heap).

Теперь мы хотим запланировать еще один рейс, который приземлится в t. Следовательно, нам нужно вычислить разницу t с его преемником и предшественником (должно быть> d). Таким образом, для этого нам понадобится BST, который делает это быстро, т.е. за O (logn), если сбалансировано.

ИЗМЕНЕНО:

Сортировка BST занимает O (n) времени для печати элементов в отсортированном порядке (Inorder Traversal), в то время как Heap может сделать это за O (n logn) времени. Куча извлекает минимальный элемент и повторно заполняет массив, что заставляет его выполнять сортировку за время O (n logn).

person CODError    schedule 01.04.2015
comment
да. От несортированной к отсортированной последовательности. Время O (n) для обхода BST по порядку, что дает отсортированную последовательность. Находясь в кучах, вы извлекаете элемент min, а затем повторно загружаете в кучу за время O (log n). Итак, для извлечения n элементов потребуется O (n logn). И это оставит вас с отсортированной последовательностью. - person CODError; 01.04.2015
comment
from unsorted to sorted sequence. O(n) time for inorder traversal of a BST, which gives sorted sequence. Что ж, от несортированной последовательности к BST я не знаю метода, основанного на сравнении ключей с временем менее O (n logn), который доминирует над частью BST для последовательности. (В то время как существует конструкция кучи O (n).) Я бы счел справедливым (если не бессмысленным) утверждать, что кучи близки к несортированности, а BST отсортированы. - person greybeard; 01.04.2015
comment
Я пытаюсь объяснить, что если у вас есть BST, а также куча из n элементов = ›, тогда все элементы могут быть напечатаны в отсортированном порядке из обеих структур данных, и BST может сделать это за O (n) время (Inorder traversal ), а Heap - время O (n logn). Я не понимаю, что вы здесь пытаетесь сказать. Как вы говорите, BST выдаст вам отсортированную последовательность за O (n logn). - person CODError; 02.04.2015
comment
Я думаю, вы также учитываете время, потраченное на создание BST и кучи. Но я предполагаю, что он у вас уже есть, что вы построили его с течением времени, и теперь вы хотите получить отсортированный результат. Я не понимаю твою точку зрения? - person CODError; 02.04.2015
comment
Отредактировано ... Надеюсь, теперь вы удовлетворены; p и поставьте +1, если все правильно. - person CODError; 02.04.2015

Вставка всех n элементов из массива в BST занимает O (n logn). n элементов в массиве могут быть вставлены в кучу за O (n) раз. Что дает куче несомненное преимущество

person AMR    schedule 29.06.2014

Куча просто гарантирует, что элементы на более высоких уровнях больше (для max-heap) или меньше (для min-heap), чем элементы на более низких уровнях.

Мне нравится приведенный выше ответ, и я помещаю свой комментарий только в соответствии с моими потребностями и использованием. Мне пришлось получить список n местоположений, чтобы найти расстояние от каждого местоположения до конкретной точки, скажем (0,0), а затем вернуть местоположения a m, имеющие меньшее расстояние. Я использовал очередь приоритетов, которая является кучей. Для определения расстояний и помещения в кучу мне потребовалось n (log (n)) n местоположений log (n) на каждую вставку. Тогда для получения m с кратчайшими расстояниями потребовалось m (log (n)) m-location log (n) удалений скопления.

Если бы мне пришлось сделать это с помощью BST, мне потребовалось бы n (n) вставки в худшем случае. (Скажем, первое значение очень меньше, а все остальные идут последовательно все длиннее и длиннее, а дерево охватывает только правый дочерний элемент или левый дочерний элемент. в случае меньшего и меньшего.Минимальное время заняло бы O (1), но снова мне пришлось сбалансировать.Так что из моей ситуации и всех вышеперечисленных ответов я получил, когда вы только после значений с минимальным или максимальным приоритетом для кучи.

person Sahib Khan    schedule 01.10.2017