Кажется, что везде, где я смотрю, структуры данных реализуются с использованием красно-черных деревьев ( std::set
в C ++, SortedDictionary
в C # и т. Д.)
Только что покрыв (a, b), красно-черные и AVL деревья в своем классе алгоритмов, вот что я получил (также из бесед с профессорами, просмотра нескольких книг и поиска в Google):
- Деревья AVL имеют меньшую среднюю глубину, чем красно-черные деревья, и, следовательно, поиск значения в дереве AVL всегда происходит быстрее.
- Красно-черные деревья вносят меньше структурных изменений в баланс, чем деревья AVL, что может сделать их потенциально более быстрыми для вставки / удаления. Я говорю потенциально, потому что это будет зависеть от стоимости структурных изменений в дереве, так как это будет сильно зависеть от времени выполнения и реализации (может также быть совершенно другим в функциональном языке, когда дерево неизменяемое?)
В Интернете есть много тестов, которые сравнивают AVL и красно-черные деревья, но что меня поразило, так это то, что мой профессор в основном сказал, что обычно вы делаете одну из двух вещей:
- Либо вас не очень заботит производительность, и в этом случае разница между AVL и красно-черным в 10-20% в большинстве случаев не будет иметь никакого значения.
- Или вы действительно заботитесь о производительности, в этом случае вы отказываетесь от AVL и красно-черных деревьев и переходите на B-деревья, которые можно настроить, чтобы они работали намного лучше (или (a, b) -деревьями, я Я собираюсь положить все это в одну корзину.)
Причина этого в том, что B-дерево хранит данные более компактно в памяти (один узел содержит много значений), поэтому кэш-памяти будет значительно меньше. Вы также можете настроить реализацию в зависимости от варианта использования и установить порядок B-дерева в зависимости от размера кэша ЦП и т. Д.
Проблема в том, что я не могу найти практически ни одного источника, который бы анализировал реальное использование различных реализаций деревьев поиска на реальном современном оборудовании. Я просмотрел много книг по алгоритмам и не нашел ничего, что сравнивало бы разные варианты дерева, кроме того, что показывал, что одна имеет меньшую среднюю глубину, чем другая (что на самом деле не говорит о том, как будет вести себя дерево в реальных программах.)
При этом существует ли конкретная причина, по которой красно-чёрные деревья используются повсеместно, когда B-деревья должны превосходить их, основываясь на том, что сказано выше? (в качестве единственного эталонного теста, который я смог найти, также показано http://lh3lh3.users.sourceforge.net/udb.shtml , но это может быть просто вопросом конкретной реализации). Или причина, по которой все используют красно-черные деревья, потому что их довольно легко реализовать, или, говоря другими словами, сложно реализовать плохо?
Кроме того, как это меняется, когда вы переходите в область функциональных языков? Похоже, что и Clojure, и Scala используют попытки сопоставления массивов Hash , где Clojure использует коэффициент ветвления 32.