Сбалансированные и идеально сбалансированные бинарные деревья поиска

Бинарное дерево называется сбалансированным, если для любой его вершины v высоты левого и правого поддерева, выходящих из v (т.е. поддеревьев с корнями v->left и v->right), отличаются не более чем на 1.

Бинарное дерево называется идеально сбалансированным, если длины всех ветвей, начинающихся в корне дерева и заканчивающихся в узле с хотя бы одним из нулевых указателей v->left и v->right, отличаются не более чем на 1.

В литературе встречается другое (неравносильное) определение идеально сбалансированных деревьев. Будем называть идеально сбалансированными’ деревьями такие деревья, для которых для каждой вершины количество элементов в левом и правом поддереве отличается не более, чем на единицу.

 

Описание: Описание: Описание: Описание: Описание: Описание: Описание: Описание: Описание: Описание: Описание: Описание: Описание: p3Описание: Описание: Описание: Описание: Описание: Описание: Описание: Описание: Описание: Описание: Описание: Описание: Описание: p2Описание: Описание: Описание: Описание: Описание: Описание: Описание: Описание: Описание: Описание: Описание: Описание: Описание: 1

 

Следующее условие равносильно условию идеально сбалансированности дерева: длины любых двух ветвей, начинающихся в одной вершине дерева, отличаются не более чем на 1. Доказательство тривиально. Из данного условия сразу же вытекает

Теорема. Идеально сбалансированное дерево является сбалансированным.

 

Иными словами, можно сказать, что для идеально сбалансированного дерева полностью заполнены элементами все слои дерева, кроме, быть может, последнего. Т.о. для идеально сбалансированного дерева высоты h количество элементов лежит в пределах 2h-1£N<2h. из чего сразу же вытекает следующая элементарная

Теорема. Для идеально сбалансированного дерева, состоящего из N вершин, высота дерева h лежит в пределах

log2 N < h £ 1+ log2 N.

Оказывается, верна следующая

Теорема. Идеально сбалансированное’ дерево является идеально сбалансированным.

Доказательство. Докажем данную теорему по индукции. Для деревьев высоты не более 1 теорема верна. Пусть для деревьев высоты h теорема верна, докажем ее для деревьев высоты h +1.

По определению идеально сбалансированных’ деревьев, каждое поддерево такого дерева – идеально сбалансировано’, а по условию индукции левое и правое поддеревья корня дерева высоты h+1 – идеально сбалансированы. В идеально сбалансированных деревьях высоты l для количества элементов дерева N выполнено соотношение 2l-1£N<2l, из чего сразу вытекает: если у двух идеально сбалансированных деревьев количество элементов в них отличается не более, чем на единицу, то либо их высоты равны, либо (если количество элементов в них, соответственно, равно 2l-1 и 2l) в меньшем дереве последний слой полностью заполнен. В обоих случаях длины всех ветвей обоих деревьев, начинающихся в корне, заканчивающихся в вершинах, не имеющих хотя бы одного потомка, отличаются не более, чем на единицу. Отсюда сразу вытекает, что и для дерева, полученного с помощью объединения двух таких деревьев с помощью общего корневого элемента, длины всех ветвей, начинающихся в корне, заканчивающихся в вершинах, не имеющих хотя бы одного потомка, отличаются не более, чем на единицу.

¢

 

Для сбалансированного дерева верна оценка высоты дерева через количество вершин в нем, аналогичная по порядку оценке для идеально сбалансированных деревьев.

Теорема. Для сбалансированного дерева, состоящего из N вершин, высота дерева h имеет оценку:

 h =Q( log2 N ).

Доказательство. Пусть tn – минимальное количество элементов в сбалансированном дереве высоты n. Тогда верна рекурсивная формула

tn=tn-1+tn-2+1

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

Уравнение tn-tn-1-tn-2=1  имеет общее решение вида

tn=с1l1n + с1l2n –1

где li  являются решениями уравнения l2-l-1=0. Из этого следует, что

tn= ( (1+sqrt(5))/2 )n (1+o(1))

после логарифмирования последнего равенства мы сразу получаем требуемое соотношение:

log2 C1  + log2 tn   n log2 ( (sqrt(5)+1)/2 )

n ≤ (log2 tn + log2 C1)/ log2 ( (sqrt(5)+1)/2 )

для некоторого C1>0. Или, в исходных обозначениях,:

h ≤ log2 N / log2 ( (sqrt(5)+1)/2 )+ log2 C2 1.45 log2 N+ C

 

¢

Операции с идеально сбалансированным деревом

Выше мы описали ряд алгоритмов выполнения базовых операций для деревьев поиска. К сожалению, не существует быстрых алгоритмов, для выполнения этих операций для идеально сбаланированных деревьев. Однако, определение идеально сбаланированного’ дерева, фактически, дает нам алгоритм его построения, что сразу же дает нам возможность строить и идеально сбаланированное дерево по тому же набору элементов. Для построения идеально сбаланированного’ дерева по набору из N элементов упорядочим этот набор. После этого алгоритм построения дерева сводится к разбиению полученной последовательности {ai}i=1,…,N на последовательности {ai}i=1,…,[N/2] и {ai}i=[N/2]+2,…,N. Эти последовательности либо имеют равную длину (для нечетных N), либо их длина отличается не более, чем на единицу (для четных N). В корень создаваемого дерева помещаем элемент a[N/2]+1 , а левое и правое поддеревья строим таким же алгоритмом, соответственно, для последовательностей {ai}i=1,…,[N/2] и {ai}i=[N/2]+2,…,N.

Итак, приведенный алгоритм доказывает следующую теорему:

Теорема. Идеально сбалансированное’ (а значит и идеально сбалансированное) дерево поиска, состоящее из N вершин, можно построить за время, равное  O(N log2 N).

 

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

Отметим, что наша задача выродилась. Идеально сбалансированные деревья полезны только для поиска элементов в этих деревьях, но тогда дерево вообще не нужно строить! Достаточно ограничиться упорядоченным массивом исходных элементов, а поиск производить с помощью бинарного поиска. В этом случае, согласно построению идеально сбалансированного дерева’, поиск по дереву будет в точности совпадать с поиском по массиву, что делает само дерево ненужным.

Операции со сбалансированным деревом

Оказывается, что для сбалансированных деревьев все описанные выше операции можно модифицировать так, что они будут сохранять сбалансированность дерева, при этом, время их выполнения не будет превышать O(log2 N) операций. Везде далее, говоря о сбалансированных деревьях, будем подразумевать, что мы имеем дело с сбалансированными деревьями поиска.

Правым и левым поддеревьями некоторой вершины дерева v называются поддеревья с корнями v->left и v->right, соответственно.

Балансом вершины дерева будем называть разность высот левого и правого поддеревьев этой вершины.

Поиск элемента в дереве

Не отличается от случая стандартных деревьев поиска.

Добавление элемента в дерево

Рассмотрим вершину дерева a, в которой нарушается баланс после добавления элемента. Все нижесказанное будет верным, если это не оговорено особо, и для случая какого-либо изменения одного из поддеревьев вершины a, приводящего к удлинению/укорачиванию соответствующего дерева на 1.

Будем предполагать, что для всех вершин, лежащих ниже a, баланс по модулю не превосходит 1.

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

То, что дерево после добавления вершины разбалансировалось, означает, что до добавления вершины [a]=1, а после добавления [a]=2 (будем обозначать баланс вершины с помощью квадратных скобок: баланс вершины a = [a]). Возможны три случая баланса вершины b после изменения дерева: 1, 0, -1. Рассмотрим их

1.После добавления вершины  [b]=1 или 0 (или изменения поддерева с корнем b) ([b]=1 соответствует удлинению левого поддерева b)

На рисунке варианты [b]=1 или 0 печатаются через слеш (косую черту).

Приведенную здесь перестановку вершин (с соответствующими поддеревьями) будем называть правым поворотом (в соответствии с перемещением вершин d-b-a).

Будем обозначать высоты дерева с корнем в вершине x  hx , а баланс этой вершины [x].

Пусть he=h, тогда для случая  [b]=1

hd=h+1         (т.к. [b]=1)

hb=h+2

ha=h+3

hc=h             (т.к. [a]=2)

Из чего сразу следует, что после правого поворота

[a]=[b]=0

[c], [d], [e] не изменились

 

Т.о. данное дерево сбалансировалось. При этом, если изменение дерева произошло в результате добавления вершины, его высота не изменилась. Действительно, перед добавлением вершины hd=h из чего следует, что перед добавлением вершины ha=h+2. После добавления высота не изменилась.  Т.о. в случае  [b]=1 процесс балансировки дерева завершен.

Для случая [b]=0 нарисованное дерево тоже остается сбалансированным:

hd=h             (т.к. [b]=0)

hb=h+1

ha=h+2

hc=h-1          (т.к. [a]=2)

Из чего сразу следует, что после правого поворота

[a]=1, [b]=-1

[c], [d], [e] не изменились.

Однако высота всего нарисованного дерева изменяется (была до добавления ha=h+1, стала ha=h+2).

 

Итак, если перед изменением дерева hb=1, то процесс балансировки завершен. Иначе, может разбалансироваться родитель вершины a, и для нее нужно выполнить тот же алгоритм.

 

2.После добавления вершины [b]=-1 (или изменения поддерева с корнем b) (удлинение правого поддерева b)

 

Описанная перестановка может быть проведена за два вращения: левого g-e-b и правого b-e-a:

 

Возможны три варианта баланса c: [c]=0/1/-1. Пусть he=h, тогда, в соответствии с возможными вариантами [c] имеем:

hf=h-1/h-1/h-2

hg=h-1/h-2/h-1

hd=h-1

hb=h+1

ha=h+2

hc=h-1

Из чего сразу следует, что после правого поворота

[b]=0/0/1

[a]=0/-1/0

[e]=0

 [d], [f] , [g] , [c] не изменились.

 

Т.о. данное нарисованное дерево сбалансировалось. При этом, если изменение дерева произошло в результате добавления вершины, его высота не изменилась. Действительно, перед добавлением вершины he=h-1 из чего следует, что перед добавлением вершины ha=h+1. После добавления высота не изменилась.  Т.о. в случае добавления вершины при   [b]=-1 процесс балансировки дерева завершен.

 

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

Итак, мы доказали следующую теорему

Теорема. В сбалансированное дерево поиска, состоящее из N вершин, можно добавить одну вершину за время O(log2 N). При этом, для балансировки дерева потребуется не более двух поворотов.

 

Отметим, что хотя балансировок требуется не более двух, весь процесс балансировки, все же, требует времени O(log2 N), т.к. требуется еще найти – в какой вершине следует производить балансировку.

Удаление элемента из дерева

Удаление вершины из дерева поиска описано в параграфе Бинарные деревья поиска. Нам остается только сбалансировать, возможно, разбалансированное дерево.

Т.о. процедура удаления вершины v из сбалансированного дерева поиска сводится к следующему

·         нахождению вершины v, которую следует удалить,

·         ее удаления из дерева поиска (с помещением на ее место некторой вершины v'),

·         для каждой вершины ветви дерева от v' до корня  следует проверять условие балансировки – если оно нарушилось, то операциями вращения следует произвести балансировку соответствующего поддерева.

 

Итак, в силу построения алгоритма удаления вершины из сбалансированного дерева, верна

Теорема. Из сбалансированного дерево поиска, состоящего из N вершин, можно удалить одну вершину за время O(log2 N).

 

Поиск минимального и максимального элемента в дереве

Не отличается от случая стандартных деревьев поиска.

Поиск следующего/предыдущего элемента в дереве

Не отличается от случая стандартных деревьев поиска.

Слияние двух деревьев

Для двух сбалансированных деревьев поиска T1 и T2 таких, что все элементы в T1  меньше или равны всех элементов в T2 : слияние деревьев в одно дерево поиска T.

Выбираем из дерева T2 наименьший элемент v (самый левый) и удаляем его из дерева T2  . Элемент v  называется стыковочным. Для него верно: T1£ v£ T2 .

Возможна ситуация, когда стыковочный элемент присутствует уже в постановке задачи.

Будем, для определенности, предполагать, что высота дерева T1 больше или равна высоте дерева T2.

Рассмотрим правую ветвь дерева T1 : {v1,…,vK}. В силу сбалансированности дерева имеем: h(vi) - h(vi+1)  £ 2, тогда на этой ветви найдется вершина vl, такая что

h(vl) = h(T2)  или h(vl) = h(T2)+1

Сольем дерево с корнем в vl и  T2 с помощью стыковочной вершины v и подставим новое дерево на место старой вершины vl.

Вершина vl и все дерево, с нее начинающееся, окажутся сбалансированными. Высота же дерева, начинающегося с vl, увеличится на 1, т.к. h(T2) £h(vl) .

Итак, в результате изменений дерева у одной вершины w длина соответствующего поддерева увеличилась на 1. Далее нам следует запустить стандартную процедуру балансировки дерева. Мы должны пройти ветвь, заканчивающуюся на w, от w до корня и в каждой вершине проверить баланс. Если он будет по модулю больше 1, то баланс в данной вершине следует скорректировать одним или двумя вращениями.

Если, при этом, длина данного поддерева восстановится до значения, которому она была равна до слияния деревьев, то далее процесс проверки сбалансированности производить не надо (т.к. дерево T1 до слияния было сбалансированным). Иначе, процесс проверки следует продолжить.

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

 

Этот вариант не мог реализоваться при добавлении одной вершины к дереву. В этом случае до слияния деревьев высота дерева с корнем a была равна h+1, а после слияния она стала равной h+2.

Итак, в силу построения алгоритма слияния двух  сбалансированных деревьев, верна

Теорема. Для двух сбалансированных деревьев поиска T1 и T2  , состоящих из N1 и N2 вершин, имеющих высоты h1 и h2,  и элемента v, таких, что все элементы в T1  меньше или равны v и v меньше или равно всех элементов в T2 : слияние деревьев с помощью стыковочного элемента v в одно сбалансированное дерево поиска T можно произвести за время T=O(log2 (N1+N2) ) или за время T=O(|h1-h2|). Указанные деревья T1 и T2 можно слить за время T=O(log2 (N1+N2) ).

 

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

 

 

Разбиение дерева по разбивающему элементу

Для данной вершины дерева v разбиение сбалансированного дерева поиска T на два сбалансированных дерева поиска T1 и T2 таких, что все элементы в T1  меньше или равны v, и все элементы в T2  больше или равны v.

Описание: Описание: Описание: Описание: Описание: Описание: Описание: Описание: Описание: Описание: Описание: Описание: Описание: p1

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

Пусть высота дерева T0 равна s0. Пусть с деревом T0 будут последовательно сливаться деревья T с индексами i1,…,iK (iK£h), в результате чего будут получаться деревья S1, S2,…, SK . Будем считать S0= T0.  Т.е. Sj-1+ Tij ® Sj .

Высота дерева Sj равна либо MAX(h(Sj-1),h(Tij )), либо MAX(h(Sj-1),h(Tij ))+1.

Пусть Ri – деревья с корнями в вершинах vi. Высота дерева Ri равна либо h(Ti)+1 либо h(Ti)+2. h(Ri) строго возрастают.

Покажем по индукции , что высота дерева Sj равна либо h(Rij), либо h(Rij)-1, либо h(Rij)-2. Пусть данное свойство выполнено для l<j, тогда

h(Sj )=MAX(h(Sj-1),h(Tij )) | MAX(h(Sj-1),h(Tij ))+1 следовательно

h(Sj )= MAX(h(Sj-1),h(Rij) -1) | MAX(h(Sj-1),h(Rij) -2) |

MAX(h(Sj-1),h(Rij) -1)+1 | MAX(h(Sj-1),h(Rij) -2)+1 следовательно по индукции

h(Sj )= (h(Rij) -1) | ((h(Rij) -1) | h(Rij) -2) |

h(Rij)  |                 (h(Rij) | h(Rij) -1) следовательно

h(Sj )= h(Rij) | (h(Rij) -1) | (h(Rij) -2)

Здесь под вертикальной чертой подразумевается разделение возможных вариантов.

Время работы всего алгоритма

T=O(|h(T0)- h(Ti1 )|+1 +| h(S1)- h(Ti2 )|+1 +…+| h(SK-1) - h(TiK )|+1)=

=O(|h(T0)- h(Ti1 )| +| h(S1)- h(Ti2 )| +…+| h(SK-1) - h(TiK )|)+O(h)=

=O(|h(T0 )- h(Ri1 )|+4 +| h(Ri1 )- h(Ri2 )|+4 +…+| h(Ri(K-1) ) - h(RiK )|+4)+O(h)=

(в силу возрастания  h(Ri) )

=O(|h(T0 )- h(Ri1 )|+| h(Ri1 )- h(Ri2 )|+…+| h(Ri(K-1) ) - h(RiK )|)+O(h)= O(h)

 

Т.о.  T= O(h)=O(log2 N), где Nколичество вершин в суммарном дереве.

Итак, верна следующая

Теорема. Для данной вершины v сбалансированного дерева поиска T разбиение на два сбалансированных дерева поиска T1 и T2 таких, что все элементы в T1  меньше или равны v, и все элементы в T2  больше или равны v. может быть произведено указанным алгоритмом за время  = O(log2 N), где Nсуммарное количество вершин в деревьях T1 и T2.