Scapegoat Tree — различия между версиями
| Kolchanov (обсуждение | вклад) | Kolchanov (обсуждение | вклад)   (→Вставка элемента) | ||
| Строка 49: | Строка 49: | ||
|        size = totalSize |        size = totalSize | ||
| + | Сама вставка элемента: | ||
| + | *<tex>k</tex> {{---}} ключ, который будет добавлен в дерево. | ||
| − | + |  '''Insert'''(k): | |
| + |    height = InsertKey(k) | ||
| + |    '''if''' height = −1: | ||
| + |       '''return''' false; | ||
| + |    '''else if''' height > T.hα: | ||
| + |       scapegoat = FindScapegoat(Search(T.root, k)) | ||
| + |       RebuildTree(n.size(), scapegoat) | ||
| + |    '''return''' true | ||
| == Оценка времени работы == | == Оценка времени работы == | ||
Версия 14:16, 17 июня 2016
Scapegoat Tree — структура данных, представляющая собой частично сбалансированное дерево поиска (степень сбалансированности может быть настроена), такое что операции поиска, вставки и удаления работают за O(log n), при этом скорость одной операции может быть улучшена в ущерб другой.
Идея
При работе необходимо поддерживать состояние сбалансированного дерева, иначе время работы операции поиска может превысить . В Scapegoat Tree используется следующая идея: введем коэффициент , который показывает, насколько дерево может быть несбалансированным. Математически это выглядит следующим образом: ; ; , где и - размер левого и правого поддерева вершины .
Если условие нарушается, запускается операция перебалансировки дерева. Заметим, что при , деревом будет считаться даже линейная структура.
Свойства
Данная структура обладает следующими свойствами:
- Выбор коэффициента позволяет ускорить некоторые операции. Например, выбор большого значения позволит выполнять очень много операций вставки, но замедлит операции поиска. При этом выбор коэффициента можно выполнять в процессе выполнения, опираясь на входные данные. Однако, неправильный выбор приводит к сильному увеличению времени работы.
- Не требуется проводить перебалансировку дерева при поиске, что гарантирует максимальное время работы поиска .
- В некоторых случаях операции модификации занимают , хотя из амортизированная сложность - .
- За счет отсутствия необходимости хранить дополнительные данные в вершинах данное дерево оптимальнее остальных по памяти.
Операции
Поиск
- — корень дерева или поддерева, в котором происходит поиск.
- — искомый ключ в дереве.
Search(root, k):
  if  root = null or root.key = k:
     return  root
  else if  k ≤ root.lef t.key:
     return  Search(root.lef t, k)
  else:
     return  Search(root.right, k)
Вставка элемента
Пока дерево остается -сбалансированным, выполняем модифицированную вставку элемента в дерево, которая аналогична обычной вставке в двоичное дерево, но операция будет возвращать глубину данной вершины.
Нам нужна специальная функция , которая позволяет найти тот элемент дерева, который испортил баланс (именно из-за этой процедуры дерево так называется. Scapegoat - "козел отпущения", который испортил баланс).
- — узел дерева. Обычно, процедура вызывается от только что добавленной вершины.
FindScapegoat(n):
  size = 1
  height = 0
  while (n.parent <> null):
     height = height + 1
     totalSize = 1 + size + n.sibling.size()
     if height > ⌊log1/α(totalSize)⌋:
        return n.parent
     n = n.parent
     size = totalSize
Сама вставка элемента:
- — ключ, который будет добавлен в дерево.
Insert(k):
  height = InsertKey(k)
  if height = −1:
     return false;
  else if height > T.hα:
     scapegoat = FindScapegoat(Search(T.root, k))
     RebuildTree(n.size(), scapegoat)
  return true
