Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
algoritmy.docx
Скачиваний:
15
Добавлен:
27.09.2019
Размер:
237.74 Кб
Скачать

13.Рандомизированные деревья. Вставка элемента в рандомизированное бинарное дерево поиска.

  • В идеально

сбалансированном дереве  трудоемкость поиска составляет О(log2 n) , а построение дерева по трудоемкости пропорционально  О(n*log2  n). Но поддержание идеально сбалансированного дерева при включении новых элементов требует больших затрат, поэтому при балансировке используются более мягкие критерии. Если внешние узлы дерева расположены на одном, в крайнем случае, двух нижних уровнях, то обеспечивается достаточно высокая производительность.

Существует много BST-деревьев,  высота которых ограничена величиной 2*log2 n.

Один из методов балансировки – построение рандомизированных BST-деревьев [4].

Включение элемента в рандомизированное дерево

При построении рандомизированного дерева основное исходное положение заключается в том, что любой элемент может с одинаковой вероятностью быть корнем дерева. Причём это справедливо и для поддеревьев рандомизированного дерева. Поэтому при включении нового элемента в дерево, случайным образом выбирается включение элемента в качестве листа, или в качестве корня. Вероятность появления нового узла в корне дерева или поддерева определяется, как 1/(n+1), где n – число узлов в дереве или в поддереве. То есть, дерево выглядит так, будто элементы поступали в него в случайном порядке. Поскольку принимаемые алгоритмом решения являются случайными,  при каждом выполнении алгоритма при одной и то же последовательности включений будут получаться деревья различной конфигурации. Таким образом, несмотря  на увеличение трудоёмкости операции включения, за счет рандомизации получается структура дерева, близкая к сбалансированной. Благодаря сбалансированности дерева трудоёмкость в рандомизированном дереве имеет оценку О(log2n) и в среднем операции более эффективны, чем в BST-дереве.

Рекурсивный алгоритм вставки в рандомизированное дерево:

RND_Insert(t, k, data, inserted)

1.   t – корень дерева или поддерева

2.     k –ключ нового элемента

3.    data – данные нового элемента

4.    inserted – возвращаемый признак вставки

5.   if t = nil

6.        then  tCreate_Node(k, data)

7.                  n[t] ← 1

8.                  inserted ← TRUE

9.                  return t

10. if Rand() < RAND_MAX/(n[t]+1)

11.      then  tRoot_Insert(t, k, data, ins)

12.                inserted ← ins

13.                return t

14. if k = key[t]

15.      then inserted ← FALSE

16.              return t

17. if k < key[t]

18.      then left[t] ← RND_Insert (left[t], k, data, ins)

19.      else  right[t] ← RND_Insert (right[t], k, data, ins)

20. inserted ← ins

21. if inserted = TRUE

22.      then n[t] ← n[t] + 1

23. return t

 

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

Поиск в рандомизированном дереве ведется по стандартному алгоритму поиска в BST – дереве. Благодаря сбалансированности дерева в среднем поиск оценивается нотацией O(log2 n) и более эффективен, чем в  BST – дереве.

Недостатком приведенного алгоритма являются затраты на генерацию случайных чисел в узлах, лежащих на пути операции включения. Чтобы минимизировать эти затраты, можно вместо системного генератора случайных чисел использовать числа, которые не являются совершенно случайными, но для генерации требуют небольших затрат. Например, функцию  Rand() можно заменить проверкой условия 111 mod n[t] = 3 для принятия решения о вставке в корень [4].

Второй недостаток – необходимость поддержки параметра n[t] в узлах рандомизированного дерева. Но, если этот параметр необходим по другим причинам, например для решения задач о порядковых статистиках, то этот недостаток не является решающим.

  • Вставка элемента x во множество. Выполняется так:

Начинаем с корневого узла дерева (его адрес записан в root). Сравниваем x со значением v в этом узле. Если они равны, то мы нашли x и делать ничего не надо – выходим из процедуры. Если x меньше v, то переходим по левому указателю (left), если больше – по правому (right). Продолжаем делать так до тех пор, пока указатель, по которому надо переходить, не окажется NIL. В этом случае создаём новый узел и его адрес помещаем в этот указатель.

И не забываем ещё один нюанс. Если элемент вставляется в пустое дерево, то адрес созданного узла нужно записать в переменную root.

Приведём пример реализации:

procedure ins(var root: PNode; x: integer);

var

r: PNode;

begin

if root=NIL then begin

new(root);

root^.left:=NIL; root^.right:=NIL; root^.v:=x;

exit;

end;

r:=root;

repeat

if r^.v=x then exit;

if x<r^.v then

begin

if r^.left<>NIL then

r:=r^.left

else

begin

new(r^.left);

r:=r^.left;

r^.left:=NIL; r^.right:=NIL; r^.v:=x;

exit;

end

end

else

begin

if r^.right<>NIL then

r:=r^.right

else

begin

new(r^.right);

r:=r^.right;

r^.left:=NIL; r^.right:=NIL; r^.v:=x;

exit;

end;

end;

until false;

end;

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]