Балансировка бинарного дерева (AVL) - PullRequest
14 голосов
/ 25 сентября 2008

Хорошо, это еще один пример из теории для парней из CS.

В 90-х я неплохо справился с реализацией BST. Единственное, что я никогда не мог понять, - это сложность алгоритма балансировки двоичного дерева (AVL).

Можете ли вы, ребята, помочь мне в этом?

Ответы [ 7 ]

16 голосов
/ 25 сентября 2008

Я не думаю, что здесь стоит публиковать полные коды для алгоритмов балансировки узлов, поскольку они становятся достаточно большими. Однако статья Википедии о красно-черных деревьях содержит полную реализацию алгоритма на языке C, а статья о деревьях AVL также содержит несколько ссылок на реализации высокого качества.

Этих двух реализаций достаточно для большинства сценариев общего назначения.

15 голосов
/ 25 сентября 2008

Дерево козла отпущения, возможно, имеет самый простой для понимания алгоритм определения баланса. Если какая-либо вставка приводит к тому, что новый узел становится слишком глубоким, он находит узел, вокруг которого необходимо выполнить балансировку, рассматривая баланс веса, а не баланс высоты. Правило перебалансировки при удалении также простое. Он не хранит никакой тайной информации в узлах. Труднее доказать, что это правильно, но вам не нужно это понимать алгоритм ...

Однако, в отличие от AVL, он не всегда сбалансирован по высоте. Как и красно-черный, его дисбаланс ограничен, но в отличие от красно-черного он настраивается с помощью параметра, поэтому для большинства практических целей он выглядит настолько сбалансированным, насколько это необходимо. Я подозреваю, что если вы настроите его слишком плотно, он окажется плохим или хуже, чем AVL для худших вставок.

Ответ на вопрос edit

Я предоставлю свой личный путь к пониманию деревьев AVL.

Сначала вы должны понять, что такое ротация деревьев, поэтому игнорируйте все остальное, что вы когда-либо слышали алгоритмы AVL, и поймите это. Получите прямо в своей голове, который является вращением вправо и вращением влево, и то, что каждый из них делает с деревом, иначе описания точных методов просто запутают вас.

Далее, поймите, что хитрость для балансировки деревьев AVL заключается в том, что каждый узел записывает в нем разницу между высотой своего левого и правого поддеревьев. Определение «сбалансированной высоты» состоит в том, что это значение составляет от -1 до 1 включительно для каждого узла в дереве.

Далее, поймите, что если вы добавили или удалили узел, возможно, вы разбалансировали дерево. Но вы можете изменить только баланс узлов, которые являются предками добавленного или удаленного вами узла. Итак, что вы собираетесь сделать, это вернуться обратно к дереву, используя повороты, чтобы уравновесить любые несбалансированные узлы, которые вы найдете, и обновлять их баланс, пока дерево снова не будет сбалансировано.

Заключительная часть понимания этого состоит в том, чтобы найти в приличном справочнике конкретные вращения, используемые для балансировки каждого узла, который вы найдете: это его «техника» в отличие от высокой концепции. Вы должны помнить детали только при изменении кода дерева AVL или, возможно, во время экзаменов структур данных. Прошло много лет с тех пор, как в последний раз у меня был код дерева AVL настолько открытым, насколько он был открыт в отладчике - реализации, как правило, доходят до точки, где они работают, а затем продолжают работать. Поэтому я действительно не помню. Вы можете сортировать это на столе, используя несколько покерных фишек, но трудно быть уверенным, что у вас действительно есть все случаи (их немного). Лучше всего просто посмотреть.

Тогда нужно перевести все это в код.

Я не думаю, что просмотр списков кода очень помогает на любом этапе, кроме последнего, поэтому игнорируйте их. Даже в лучшем случае, когда код четко написан, он будет выглядеть как описание процесса из учебника, но без диаграмм. В более типичном случае это беспорядок манипулирования структурой C. Так что просто придерживайтесь книг.

4 голосов
/ 06 ноября 2008

В последнее время я работаю с деревьями AVL.

Лучшая помощь, которую я смог найти в том, как их сбалансировать, была через поиск в Google.

Я только что написал этот псевдокод (если вы понимаете, как выполнять ротацию, это довольно легко реализовать).

IF tree is right heavy
{
  IF tree's right subtree is left heavy
  {
     Perform Double Left rotation 
  }
  ELSE
  {
     Perform Single Left rotation
  }
}
ELSE IF tree is left heavy
{
  IF tree's left subtree is right heavy
  {
     Perform Double Right rotation
  }
  ELSE
  {
     Perform Single Right rotation
  }
}
1 голос
/ 25 сентября 2008

Согласен, полная программа не подходит.

Хотя в классическом дереве AVL и RB используется детерминистский подход, я бы посоветовал взглянуть на « Рандомизированные бинарные деревья поиска », которые обходятся дешевле, чтобы поддерживать баланс и гарантировать хорошую балансировку независимо от статистического распределения. из ключей.

0 голосов
/ 25 июля 2012

есть полная реализация самобалансирующегося дерева avl @ http://code.google.com/p/self-balancing-avl-tree/. он также реализует логарифмические операции конкатенации и разделения времени, а также наборы карт / мультикарт

0 голосов
/ 17 мая 2010

Для балансировки дерева AVL я только что написал несколько функций, которыми я поделился со всеми здесь. Я думаю, что эта реализация безупречна. Запросы / вопросы / критика, конечно, приветствуются:

http://uploading.com/files/5883f1c7/AVL_Balance.cpp/

Будучи новичком в Stackoverflow, я пытался опубликовать здесь свой код, но все же столкнулся с проблемами форматирования. Итак, загрузил файл по вышеуказанной ссылке.

Приветствие.

0 голосов
/ 26 сентября 2008

Дерево AVL неэффективно, потому что вам приходится делать потенциально много поворотов за вставку / удаление.

Красно-черное дерево, вероятно, является лучшей альтернативой, потому что вставки / удаления намного более эффективны. Эта структура гарантирует, что самый длинный путь к листу не более чем в два раза превышает кратчайший путь. Поэтому, будучи менее сбалансированным, чем дерево AVL, можно избежать худших несбалансированных случаев.

Если ваше дерево будет прочитано много раз и не будет изменено после его создания, оно может стоить дополнительных издержек для полностью сбалансированного дерева AVL. Также красно-черному дереву требуется один дополнительный бит памяти для каждого узла, что дает «цвет» узла.

...