Когда выбрать дерево RB, дерево B или дерево AVL?

как программист когда я должен рассматривать использование дерева RB, B-дерева или дерева AVL? Каковы ключевые моменты, которые необходимо рассмотреть, прежде чем принимать решение о выборе?

может ли кто-нибудь объяснить сценарий для каждой древовидной структуры, почему он выбран над другими со ссылкой на ключевые моменты?

4 ответов


возьмите это с щепоткой соли:

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

RB дерево, когда вы делаете довольно частые вставки, удаляет и извлекает на дереве.

дерево AVL, когда ваши вставки и удаления нечасты относительно ваших извлечений.


Я думаю, что деревья B+ - хорошая универсальная упорядоченная структура данных контейнера, даже в основной памяти. Даже когда виртуальная память не является проблемой, кэш-дружелюбие часто является, и деревья B+ особенно хороши для последовательного доступа-та же асимптотическая производительность, что и связанный список, но с кэш-дружелюбием, близким к простому массиву. Все это и O (log n) поиск, вставка и удаление.

B+ деревья имеют проблемы, хотя-такие как элементы, перемещающиеся внутри узлов, когда вы do вставки / удаления, недействительные указатели на эти элементы. У меня есть библиотека контейнеров, которая выполняет "обслуживание курсора" - курсоры прикрепляются к листовому узлу, на который они ссылаются в связанном списке, поэтому они могут быть исправлены или аннулированы автоматически. Поскольку редко бывает больше одного или двух курсоров, он работает хорошо, но это все равно дополнительная работа.

другое дело, что дерево B+ по существу является именно этим. Я думаю, вы можете снять или воссоздать non-leaf узлы в зависимости от того, нужны они вам или нет, но с узлами двоичного дерева вы получаете намного больше гибкости. Двоичное дерево можно преобразовать в связанный список и обратно без копирования узлов - вы просто меняете указатели, а затем помните, что теперь вы рассматриваете его как другую структуру данных. Среди прочего, это означает, что вы получаете довольно простое o(n) слияние деревьев - конвертируете оба дерева в списки, объединяете их, а затем конвертируете обратно в дерево.

еще одна вещь-распределение памяти и освобождение. В двоичном дереве Это можно отделить от алгоритмов - пользователь может создать узел, затем вызвать алгоритм вставки, а удаления могут извлекать узлы (отсоединять их от дерева, но не освобождать память). В B-дереве или B+-дереве это, очевидно, не работает - данные будут жить в многопозиционном узле. Написание методов вставки, которые "планируют" операцию без изменения узлов, пока они не узнают, сколько новых узлов необходимо и что они могут быть выделены, является вызов.

красный черный против AVL? Я не уверен, что это имеет большое значение. Моя собственная библиотека имеет основанный на политике класс "инструмент" для управления узлами, с методами для двойных связанных списков, простых двоичных деревьев, деревьев splay, красно-черных деревьев и treaps, включая различные преобразования. Некоторые из этих методов были реализованы только потому, что мне было скучно в тот или иной момент. Я даже не уверен, что тестировал методы treap. Причина, по которой я выбрал красно-черные деревья, а не AVL, потому что я лично я лучше понимаю алгоритмы - что не означает, что они проще, это просто случайность истории, что я более знаком с ними.

и последнее - я только первоначально разработал свои контейнеры дерева B+ в качестве эксперимента. Это один из тех экспериментов, которые никогда не заканчивались, но я бы не советовал другим повторять. Если все, что вам нужно, это упорядоченный контейнер, лучший ответ - использовать тот, который предоставляет ваша существующая библиотека-например, std::map и т. д. В C++. Мой библиотека развивалась годами, потребовалось довольно много времени, чтобы получить ее стабильной, и я только недавно обнаружил, что она технически непереносима (зависит от немного неопределенного поведения WRT offsetof).


в памяти B-Tree имеет преимущество, когда количество элементов превышает 32000... Посмотреть speedtest.формат PDF С stx-btree.


при выборе структур данных вы торгуете такими факторами, как

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

Я бы начал с чтения статей Википедии, на которые ссылается Роберт Харви.

прагматически, при работе на таких языках, как Java, среднее программист склонен использовать предоставленные классы коллекции. Если в действии настройки производительности обнаруживается, что производительность коллекции проблематична, можно искать альтернативные реализации. Это редко первое, что должно учитывать развитие под руководством бизнеса. Крайне редко нужно реализовывать такие структуры данных вручную, обычно есть библиотеки, которые можно использовать.