<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Algo1s097</id>
		<title>Викиконспекты - Вклад участника [ru]</title>
		<link rel="self" type="application/atom+xml" href="http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Algo1s097"/>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%92%D0%BA%D0%BB%D0%B0%D0%B4/Algo1s097"/>
		<updated>2026-08-03T23:04:56Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%92%D0%B7%D0%B2%D0%B5%D1%88%D0%B5%D0%BD%D0%BD%D0%BE%D0%B5_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE&amp;diff=57927</id>
		<title>Взвешенное дерево</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%92%D0%B7%D0%B2%D0%B5%D1%88%D0%B5%D0%BD%D0%BD%D0%BE%D0%B5_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE&amp;diff=57927"/>
				<updated>2016-12-17T15:42:18Z</updated>
		
		<summary type="html">&lt;p&gt;Algo1s097: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
'''Scapegoat-дерево'''  {{---}} сбалансированное [[Дерево поиска, наивная реализация | двоичное дерево поиска]], обеспечивающее наихудшее &amp;lt;tex&amp;gt;O(\log N)&amp;lt;/tex&amp;gt; время поиска, и &amp;lt;tex&amp;gt;O(\log N)&amp;lt;/tex&amp;gt; {{---}} амортизирующее время вставки и удаления элемента.&lt;br /&gt;
В отличие от большинства других самобалансирующихся бинарных деревьев поиска , которые обеспечивают худшем случае &amp;lt;tex&amp;gt;O(\log N)&amp;lt;/tex&amp;gt; время поиска, Scapegoat деревья не требуют дополнительной памяти в узлах по сравнению с обычным двоичным деревом поиска: узел хранит только ключ и два указателя на своих потомков.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Операции ==&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=Бинарное дерево поиска называется '''сбалансированным''', если половина вершин расположены слева от корня, а другая половина справа.&lt;br /&gt;
}}&lt;br /&gt;
Введем обозначения:&lt;br /&gt;
Квадратные скобки в обозначениях означают, что хранится это значение явно, а значит можно взять за время &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;. Круглые скобки означают, что значение будет вычисляться по ходу дела то есть память не расходуется, но зато нужно время на вычисление.&lt;br /&gt;
 &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; — обозначение дерева,&lt;br /&gt;
 &amp;lt;tex&amp;gt;root[T]&amp;lt;/tex&amp;gt; — корень дерева &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;, &lt;br /&gt;
 &amp;lt;tex&amp;gt;left[x]&amp;lt;/tex&amp;gt; — левый сын вершины &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;,&lt;br /&gt;
 &amp;lt;tex&amp;gt;right[x]&amp;lt;/tex&amp;gt; — правый сын вершины &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;,&lt;br /&gt;
 &amp;lt;tex&amp;gt;\mathtt{brother(x)}&amp;lt;/tex&amp;gt; — брат вершины &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; (вершина, которая имеет с &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; общего родителя),&lt;br /&gt;
 &amp;lt;tex&amp;gt;depth(x)&amp;lt;/tex&amp;gt; — глубина вершины &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;. Это расстояние от неё до корня (количество ребер),&lt;br /&gt;
 &amp;lt;tex&amp;gt;height(T)&amp;lt;/tex&amp;gt; — глубина дерева &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;. Это глубина самой глубокой вершины дерева &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;,&lt;br /&gt;
 &amp;lt;tex&amp;gt;weight(x)&amp;lt;/tex&amp;gt; — вес вершины &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;. Это количество всех её дочерних вершин + 1 (она сама),&lt;br /&gt;
 &amp;lt;tex&amp;gt;weight[T]&amp;lt;/tex&amp;gt; — размер дерева &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;. Это количество вершин в нём (вес корня),&lt;br /&gt;
 &amp;lt;tex&amp;gt;\mathtt{maxweight[T]}&amp;lt;/tex&amp;gt; — максимальный размер дерева. Это максимальное значение, которое параметр &amp;lt;tex&amp;gt;weight[T]&amp;lt;/tex&amp;gt; принимал с момента последней перебалансировки.&amp;lt;br&amp;gt; Если перебалансировка произошла только что, то &amp;lt;tex&amp;gt;\mathtt{maxweight[T]} = weight[T]&amp;lt;/tex&amp;gt;&lt;br /&gt;
[[Файл:0ce162a62b624da8ba02233b4b254f23.png]]&lt;br /&gt;
&lt;br /&gt;
Синим цветом обозначены '''глубины''' вершин, а красным - их '''веса'''.&lt;br /&gt;
Считается вес вершины следующим образом: для новой вершины вес = 1. Для её родителя вес = 1 (вес новой вершины) + 1 (вес самого родителя) + &amp;lt;tex&amp;gt;\mathtt{weight(brother(x))}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Возникает вопрос {{---}} как посчитать &amp;lt;tex&amp;gt;\mathtt{weight(brother(x))}&amp;lt;/tex&amp;gt;? Делается это рекурсивно. Это займёт время &amp;lt;tex&amp;gt;O\mathtt{(weight(brother(x)))}&amp;lt;/tex&amp;gt;. Понимая, что в худшем случае  придётся посчитать вес половины дерева — здесь появляется та самая сложность &amp;lt;tex&amp;gt;O(N)&amp;lt;/tex&amp;gt; в худшем случае, о которой говорилось в начале. Но поскольку совершается обход поддерева &amp;lt;tex&amp;gt;\alpha&amp;lt;/tex&amp;gt;-сбалансированного по весу дерева можно показать, что амортизированная сложность операции не превысит &amp;lt;tex&amp;gt;O(\log N)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
В данном Scapegoat-дереве &amp;lt;tex&amp;gt;weight[T] = 4&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\mathtt{maxweight[T]} \geqslant 4&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Коэффициeнт &amp;lt;tex&amp;gt;\alpha&amp;lt;/tex&amp;gt; — это число в диапазоне от &amp;lt;tex&amp;gt;[0.5; 1)&amp;lt;/tex&amp;gt;, определяющее требуемую степень качества балансировки дерева. &lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=Некоторая вершина &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; называется '''α - сбалансированной по весу''', если &amp;lt;tex&amp;gt;\mathtt{weight(left[x])} \leqslant \alpha  \cdot weight(x)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\mathtt{weight(right[x])} \leqslant \alpha \cdot size(x)&amp;lt;/tex&amp;gt;.}} &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Перед тем как приступить к работе с деревом, выбирается параметр &amp;lt;tex&amp;gt;\alpha&amp;lt;/tex&amp;gt; в диапазоне &amp;lt;tex&amp;gt;[0.5; 1)&amp;lt;/tex&amp;gt;. Также нужно завести две переменные для хранения текущих значений &amp;lt;tex&amp;gt;weight[T]&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\mathtt{maxweight[T]}&amp;lt;/tex&amp;gt; и обнулить их.&lt;br /&gt;
=== Поиск элемента ===&lt;br /&gt;
Пусть требуется найти в данном Scapegoat дереве какой-то элемент. Применим стандартный алгоритм для двоичного дерева поиска - идем от корня, если значение в вершине равно значению искомого элемента, возвращаем, если значение в вершине меньше, то рекурсивно запускаемся от левого поддерева, если больше, то, соответственно, от левого.&lt;br /&gt;
'''Замечание:''' Дерево по ходу поиска искомой вершины ''не изменяется''.&lt;br /&gt;
Сложность операции поиска зависит от коэффициента &amp;lt;tex&amp;gt;\alpha&amp;lt;/tex&amp;gt; и выражается формулой {{---}}  &amp;lt;tex&amp;gt;\log_\frac{1}{\alpha} (N)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Таким образом, сложность получается логарифмическая, НО! При &amp;lt;tex&amp;gt;\alpha&amp;lt;/tex&amp;gt; близком к &amp;lt;tex&amp;gt;0.5&amp;lt;/tex&amp;gt; мы получаем двоичный (или почти двоичный) логарифм, что означает практически идеальную  скорость поиска. При &amp;lt;tex&amp;gt;\alpha&amp;lt;/tex&amp;gt; близком к единице основание логарифма стремится к единице, а значит общая сложность стремится к &amp;lt;tex&amp;gt;O(N)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
=== Вставка элемента ===&lt;br /&gt;
Классический алгоритм вставки нового элемента: поиском ищем место, куда бы подвесить новую вершину, ну и подвешиваем. Легко понять, что это действие могло нарушить &amp;lt;tex&amp;gt;\alpha&amp;lt;/tex&amp;gt;-балансировку по весу для одной или более вершин дерева. И вот теперь начинается то, что и дало название нашей структуре данных: требуется найти  Scapegoat-вершину — вершину, для которой потерян &amp;lt;tex&amp;gt;\alpha&amp;lt;/tex&amp;gt;-баланс и её поддерево должно быть перестроено. Сама только что вставленная вершина, хотя и виновата в потере баланса, Scapegoat-вершиной  стать не может — у неё ещё нет потомков, а значит её баланс идеален. Соответственно, нужно пройти по дереву от этой вершины к корню, пересчитывая веса для каждой вершины по пути. Может возникнуть вопрос - нужно ли хранить ссылки на родителей? Поскольку к месту вставки новой вершины пришли из корня дерева —  есть стек, в котором находится весь путь от корня к новой вершине. Берутся родителей из него. Если на этом пути от нашей вершины к корню встретится вершина, для которой критерий &amp;lt;tex&amp;gt;\alpha&amp;lt;/tex&amp;gt;-сбалансированности по весу нарушился — тогда полностью перестраивается соответствующее ей поддерево так, чтобы восстановить &amp;lt;tex&amp;gt;\alpha&amp;lt;/tex&amp;gt;-сбалансированность по весу. &lt;br /&gt;
Сразу появляется вопрос {{---}} как делать перебалансировку найденной Scapegoat-вершины?&lt;br /&gt;
Есть 2 способа перебалансировки, {{---}} тривиальный и чуть более сложный.&lt;br /&gt;
====Тривиальный способ перебалансировки====&lt;br /&gt;
# совершается обход всего поддерева Scapegoat-вершины (включая её саму) с помощью in-order обхода — на выходе получается отсортированный список (свойство In-order обхода бинарного дерева поиска).&lt;br /&gt;
# Находится медиана на этом отрезке и подвешивается в качестве корня поддерева.&lt;br /&gt;
# Для «левого» и «правого» поддерева рекурсивно повторяется та же операция.&lt;br /&gt;
Данный способ требует  &amp;lt;tex&amp;gt;O\mathtt{(weight(Scapegoat-root))}&amp;lt;/tex&amp;gt; времени и столько же памяти.&lt;br /&gt;
====Более сложный способ перебалансировки====&lt;br /&gt;
Время работы перебалансировки вряд ли улучшится — всё-таки каждую вершину нужно «подвесить» в новое место. Но можно попробовать сэкономить память. Давайте посмотрим на 1 способ алгоритма внимательнее. Вот выбирается медиану, подвешивается в корень, дерево делится на два поддерева — и делится весьма однозначно. Никак нельзя выбрать «какую-то другую медиану» или подвесить «правое» поддерево вместо левого. Та же самая однозначность преследует и на каждом из следующих шагов. Т.е. для некоторого списка вершин, отсортированных в возрастающем порядке,  будет ровно одно порождённое данным алгоритмом дерево. А откуда же берется отсортированный список вершин? Из in-order обхода изначального дерева. То есть каждой вершине, найденной по ходу in-order обхода перебалансируемого дерева соответствует одна конкретная позиция в новом дереве. И можно эту позицию рассчитать и без создания самого отсортированного списка. А рассчитав — сразу её туда записать. Возникает только одна проблема —  этим затирается какая-то (возможно ещё не просмотренная) вершина — что же делать? Хранить её. Где? Ответ прост: выделять для списка таких вершин память. Но этой памяти нужно будет уже не &amp;lt;tex&amp;gt;O(weight(N))&amp;lt;/tex&amp;gt;, а всего лишь &amp;lt;tex&amp;gt;O(\log N)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Представьте себе в уме дерево, состоящее из трёх вершин — корня и двух подвешенных как «левые» сыновья вершин. In-order обход вернёт нам эти вершины в порядке от самой «глубокой» до корня, но хранить в отдельной памяти по ходу этого обхода нам придётся всего одну вершину (самую глубокую), поскольку когда мы придём во вторую вершину, мы уже будем знать, что это медиана и она будет корнем, а остальные две вершины — её детьми. Т.е. расход памяти здесь — на хранение одной вершины, что согласуется с верхней оценкой для дерева из трёх вершин — &amp;lt;tex&amp;gt;\log(3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Таким образом, если нужно сэкономить память, то 2 способ перебалансировки дерева {{---}} лучший вариант.&lt;br /&gt;
=== Удаление элемента ===&lt;br /&gt;
Удаляется элемент из дерева обычным удалением вершины бинарного дерева поиска (поиск элемента, удаление, возможное переподвешивание детей). &lt;br /&gt;
Далее следует проверка выполнения условия: &lt;br /&gt;
:&amp;lt;tex&amp;gt;weight[T] &amp;lt; \alpha \cdot \mathtt {maxweight[T]}&amp;lt;/tex&amp;gt;;&lt;br /&gt;
Если оно выполняется — дерево могло потерять &amp;lt;tex&amp;gt;\alpha&amp;lt;/tex&amp;gt; - балансировку по весу, а значит нужно выполнить полную перебалансировку дерева (начиная с корня) и присвоить:&lt;br /&gt;
:&amp;lt;tex&amp;gt;\mathtt {maxweight[T]} = weight[T]&amp;lt;/tex&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Сравнение с другими деревьями==&lt;br /&gt;
===Достоинства Scapegoat дерева===&lt;br /&gt;
*  По сравнению с такими структурами, как [[Красно-черное дерево]], [[АВЛ-дерево]] и [[Декартово дерево]], нет необходимости хранить какие-либо дополнительные данные в вершинах(а значит появляется выигрыш по памяти).&lt;br /&gt;
* Отсутствие необходимости перебалансировать дерево при операции поиска (а значит гарантируется максимальное время поиска &amp;lt;tex&amp;gt;O(\log N)&amp;lt;/tex&amp;gt;, в отличии от структуры данных [[Splay-дерево]], где гарантируется только амортизированное &amp;lt;tex&amp;gt;O(\log N)&amp;lt;/tex&amp;gt;)&lt;br /&gt;
* При построении дерева выбирается некоторый коэффициент &amp;lt;tex&amp;gt;\alpha&amp;lt;/tex&amp;gt;, который позволяет улучшать дерево, делая операции поиска более быстрыми за счет замедления операций модификации или наоборот. Можно реализовать структуру данных, а дальше уже подбирать коэффициент по результатам тестов на реальных данных и специфики использования дерева.&lt;br /&gt;
===Недостатки Scapegoat дерева===&lt;br /&gt;
* В худшем случае операции модификации дерева могут занять &amp;lt;tex&amp;gt;O(N)&amp;lt;/tex&amp;gt; времени (амортизированная сложность у них по-прежнему &amp;lt;tex&amp;gt;O(\log N)&amp;lt;/tex&amp;gt;, но защиты от плохих случаев нет).&lt;br /&gt;
* Можно неправильно оценить частоту разных операций с деревом и ошибиться с выбором коэффициента &amp;lt;tex&amp;gt;\alpha&amp;lt;/tex&amp;gt; — в результате часто используемые операции будут работать долго, а редко используемые — быстро, что не очень хорошо.&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Поисковые структуры данных]]&lt;br /&gt;
* [[АВЛ-дерево]]&lt;br /&gt;
* [[Декартово дерево]]&lt;br /&gt;
* [[Splay-дерево]]&lt;br /&gt;
* [[Красно-черное дерево]]&lt;br /&gt;
==Источники информации==&lt;br /&gt;
*[https://en.wikipedia.org/wiki/Scapegoat_tree Википедия - Scapegoat tree]&amp;lt;br&amp;gt;&lt;br /&gt;
*[https://habrahabr.ru/company/infopulse/blog/246759/ Хабрахабр - Scapegoat деревья]&amp;lt;br&amp;gt;&lt;br /&gt;
*[https://people.ksp.sk/~kuko/gnarley-trees/ Scapegoat Tree Applet by Kubo Kovac]&lt;/div&gt;</summary>
		<author><name>Algo1s097</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%92%D0%B7%D0%B2%D0%B5%D1%88%D0%B5%D0%BD%D0%BD%D0%BE%D0%B5_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE&amp;diff=57817</id>
		<title>Взвешенное дерево</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%92%D0%B7%D0%B2%D0%B5%D1%88%D0%B5%D0%BD%D0%BD%D0%BE%D0%B5_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE&amp;diff=57817"/>
				<updated>2016-12-14T16:44:02Z</updated>
		
		<summary type="html">&lt;p&gt;Algo1s097: /* Определение */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
'''Scapegoat-дерево'''  {{---}} сбалансированное бинарное дерево поиска, обеспечивающее наихудшее &amp;lt;tex&amp;gt;O(log N)&amp;lt;/tex&amp;gt; время поиска, и &amp;lt;tex&amp;gt;O(log N)&amp;lt;/tex&amp;gt; - амортизирующее время вставки и удаления элемента.&lt;br /&gt;
В отличие от большинства других самобалансирующихся бинарных деревьев поиска , которые обеспечивают худшем случае &amp;lt;tex&amp;gt;O(log N)&amp;lt;/tex&amp;gt; время поиска, Scapegoat деревья не требуют дополнительной памяти в узлах по сравнению с обычным двоичным деревом поиска : узел хранит только ключ и два указателя на своих потомков.&lt;br /&gt;
&lt;br /&gt;
== Достоинства Scapegoat дерева ==&lt;br /&gt;
# Отсутствие необходимости хранить какие-либо дополнительные данные в вершинах (а значит мы выигрываем по памяти у таких структур, как [[Красно-черное дерево]], [[АВЛ-дерево]] и [[Декартово дерево]])&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# Отсутствие необходимости перебалансировать дерево при операции поиска (а значит мы можем гарантировать максимальное время поиска &amp;lt;tex&amp;gt;O(log N)&amp;lt;/tex&amp;gt;, в отличии от структуры данных [[Splay-дерево]], где гарантируется только амортизированное &amp;lt;tex&amp;gt;O(log N)&amp;lt;/tex&amp;gt;)&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# Амортизированная сложность операций вставки и удаления &amp;lt;tex&amp;gt;O(log N)&amp;lt;/tex&amp;gt; — это в общем-то аналогично остальным типам деревьев&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# При построении дерева мы выбираем некоторый коэффициент «строгости» α, который позволяет улучшать дерево, делая операции поиска более быстрыми за счет замедления     операций модификации или наоборот. Можно реализовать структуру данных, а дальше уже подбирать коэффициент по результатам тестов на реальных данных и специфики использования дерева.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
== Недостатки Scapegoat дерева ==&lt;br /&gt;
# В худшем случае операции модификации дерева могут занять &amp;lt;tex&amp;gt;O(N)&amp;lt;/tex&amp;gt; времени (амортизированная сложность у них по-прежнему &amp;lt;tex&amp;gt;O(log N)&amp;lt;/tex&amp;gt;, но защиты от плохих случаев нет).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# Можно неправильно оценить частоту разных операций с деревом и ошибиться с выбором коэффициента α — в результате часто используемые операции будут работать долго, а редко используемые — быстро, что не очень хорошо.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
== Операции ==&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=Бинарное дерево поиска называется '''сбалансированным по весу''', если половина вершин расположены слева от корня, а другая половина справа.&lt;br /&gt;
}}&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Введем обозначения:'''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Квадратные скобки в обозначениях означают, что мы храним это значение явно, а значит можем взять за время &amp;lt;tex&amp;gt;О(1)&amp;lt;/tex&amp;gt;. Круглые скобки означают, что значение будет вычисляться по ходу дела то есть память не расходуется, но зато нужно время на вычисление.&lt;br /&gt;
* &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; — обозначение дерева&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* &amp;lt;tex&amp;gt;root[T]&amp;lt;/tex&amp;gt; — корень дерева &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* &amp;lt;tex&amp;gt;left[x]&amp;lt;/tex&amp;gt; — левый сын вершины x&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* &amp;lt;tex&amp;gt;right[x]&amp;lt;/tex&amp;gt; — правый сын вершины x&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* &amp;lt;tex&amp;gt;brother(x)&amp;lt;/tex&amp;gt; — брат вершины х (вершина, которая имеет с х общего родителя)&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* &amp;lt;tex&amp;gt;depth(x)&amp;lt;/tex&amp;gt; — глубина вершины х. Это расстояние от неё до корня (количество ребер)&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* &amp;lt;tex&amp;gt;height(T)&amp;lt;/tex&amp;gt; — глубина дерева T. Это глубина самой глубокой вершины дерева T&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* &amp;lt;tex&amp;gt;size(x)&amp;lt;/tex&amp;gt; — вес вершины х. Это количество всех её дочерних вершин + 1 (она сама)&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* &amp;lt;tex&amp;gt;size[T]&amp;lt;/tex&amp;gt; — размер дерева T. Это количество вершин в нём (вес корня)&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* &amp;lt;tex&amp;gt;maxsize[T]&amp;lt;/tex&amp;gt; — максимальный размер дерева. Это максимальное значение, которое параметр &amp;lt;tex&amp;gt;size[T]&amp;lt;/tex&amp;gt; принимал с момента последней перебалансировки.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt; Если перебалансировка произошла только что, то &amp;lt;tex&amp;gt;maxsize[T] = size[T]&amp;lt;/tex&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:0ce162a62b624da8ba02233b4b254f23.png]]&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Синим цветом обозначены '''глубины''' вершин, а красным - их '''веса'''.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
В данном Scapegoat-дереве &amp;lt;tex&amp;gt;size[T] = 4&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;maxsize[T] \geqslant 4&amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* Коэффициeнт α — это число в диапазоне от &amp;lt;tex&amp;gt;[0.5; 1)&amp;lt;/tex&amp;gt;, определяющее требуемую степень качества балансировки дерева. &lt;br /&gt;
&amp;lt;br&amp;gt;{{Определение&lt;br /&gt;
|definition=Некоторая вершина x называется &amp;quot;α-сбалансированной по весу&amp;quot;, если вес её левого сына меньше либо равен   &amp;lt;tex&amp;gt;\alpha \cdot size(x)&amp;lt;/tex&amp;gt; и вес ей правого сына меньше либо равен &amp;lt;tex&amp;gt;\alpha \cdot size(x)&amp;lt;/tex&amp;gt;.}} &lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
:&amp;lt;tex&amp;gt;size(left[x]) \leqslant \alpha  \cdot size(x)&amp;lt;/tex&amp;gt;;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
:&amp;lt;tex&amp;gt;size(right[x]) \leqslant \alpha \cdot size(x)&amp;lt;/tex&amp;gt;;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Перед тем как приступить к работе с деревом, мы выбираем параметр α в диапазоне &amp;lt;tex&amp;gt;[0.5; 1)&amp;lt;/tex&amp;gt;. Также заводим две переменные для хранения текущих значений &amp;lt;tex&amp;gt;size[T]&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;maxsize[T]&amp;lt;/tex&amp;gt; и обнуляем их.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
=== Поиск элемента ===&lt;br /&gt;
&amp;lt;br&amp;gt;Пусть мы хотим найти в данном Scapegoat дереве какой-то элемент. Применим стандартный алгоритм для двоичного дерева поиска - идем от корня, если значение в вершине равно значению искомого элемента, возвращаем, если значение в вершине меньше, то рекурсивно запускаемся от левого поддерева, если больше, то, соответственно, от левого.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Замечание:''' Дерево по ходу поиска искомой вершины ''не изменяется''.&amp;lt;br&amp;gt;&lt;br /&gt;
Сложность операции поиска зависит от коэффициента &amp;lt;tex&amp;gt;\alpha&amp;lt;/tex&amp;gt; и выражается формулой {{---}}  &amp;lt;tex&amp;gt;log&amp;lt;/tex&amp;gt;&amp;lt;sub&amp;gt;1/α&amp;lt;/sub&amp;gt;&amp;lt;tex&amp;gt;(N)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Таким образом, сложность получается логарифмическая, НО! При &amp;lt;tex&amp;gt;\alpha&amp;lt;/tex&amp;gt; близком к 0.5 мы получаем двоичный (или почти двоичный) логарифм, что означает практически идеальную  скорость поиска. При &amp;lt;tex&amp;gt;\alpha&amp;lt;/tex&amp;gt; близком к единице основание логарифма стремится к единице, а значит общая сложность стремится к &amp;lt;tex&amp;gt;O(N)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
=== Вставка элемента ===&lt;br /&gt;
Классический алгоритм вставки нового элемента: поиском ищем место, куда бы подвесить новую вершину, ну и подвешиваем. Легко понять, что это действие могло нарушить &amp;lt;tex&amp;gt;\alpha&amp;lt;/tex&amp;gt;-балансировку по весу для одной или более вершин дерева. И вот теперь начинается то, что и дало название нашей структуре данных: мы ищем  Scapegoat-вершину — вершину, для которой потерян &amp;lt;tex&amp;gt;\alpha&amp;lt;/tex&amp;gt;-баланс и её поддерево должно быть перестроено. Сама только что вставленная вершина, хотя и виновата в потере баланса, Scapegoat-вершиной  стать не может — у неё ещё нет потомков, а значит её баланс идеален. Соответственно, нужно пройти по дереву от этой вершины к корню, пересчитывая веса для каждой вершины по пути. Если на этом пути встретится вершина, для которой критерий &amp;lt;tex&amp;gt;\alpha&amp;lt;/tex&amp;gt;-сбалансированности по весу нарушился — мы полностью перестраиваем соответствующее ей поддерево так, чтобы восстановить &amp;lt;tex&amp;gt;\alpha&amp;lt;/tex&amp;gt;-сбалансированность по весу. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Сразу возникает вопрос {{---}} Как делать перебалансировку найденной Scapegoat-вершины?&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Есть 2 способа перебалансировки, {{---}} ниже  подробнее рассказывается о каждом из них.&lt;br /&gt;
====1 способ перебалансировки====&lt;br /&gt;
# Обходим всё поддерево Scapegoat-вершины (включая её саму) с помощью in-order обхода — на выходе получаем отсортированный список (свойство In-order обхода бинарного дерева поиска).&lt;br /&gt;
# Находим медиану на этом отрезке, подвешиваем её в качестве корня поддерева.&lt;br /&gt;
# Для «левого» и «правого» поддерева рекурсивно повторяем ту же операцию.&lt;br /&gt;
Данный способ требует  &amp;lt;tex&amp;gt;O(size(Scapegoat-root))&amp;lt;/tex&amp;gt; времени и столько же памяти.&lt;br /&gt;
====2 способ перебалансировки====&lt;br /&gt;
Мы вряд ли улучшим время работы перебалансировки — всё-таки каждую вершину нужно «подвесить» в новое место. Но мы можем попробовать сэкономить память. Давайте посмотрим на 1 способ алгоритма внимательнее. Вот мы выбираем медиану, подвешиваем в корень, дерево делится на два поддерева — и делится весьма однозначно. Никак нельзя выбрать «какую-то другую медиану» или подвесить «правое» поддерево вместо левого. Та же самая однозначность преследует нас и на каждом из следующих шагов. Т.е. для некоторого списка вершин, отсортированных в возрастающем порядке, у нас будет ровно одно порождённое данным алгоритмом дерево. А откуда же мы взяли отсортированный список вершин? Из in-order обхода изначального дерева. То есть каждой вершине, найденной по ходу in-order обхода перебалансируемого дерева соответствует одна конкретная позиция в новом дереве. И мы можем эту позицию рассчитать и без создания самого отсортированного списка. А рассчитав — сразу её туда записать. Возникает только одна проблема — мы ведь этим затираем какую-то (возможно ещё не просмотренную) вершину — что же делать? Хранить её. Где? Ответ прост: выделять для списка таких вершин память. Но этой памяти нужно будет уже не &amp;lt;tex&amp;gt;O(size(N))&amp;lt;/tex&amp;gt;, а всего лишь &amp;lt;tex&amp;gt;O(log N)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Представьте себе в уме дерево, состоящее из трёх вершин — корня и двух подвешенных как «левые» сыновья вершин. In-order обход вернёт нам эти вершины в порядке от самой «глубокой» до корня, но хранить в отдельной памяти по ходу этого обхода нам придётся всего одну вершину (самую глубокую), поскольку когда мы придём во вторую вершину, мы уже будем знать, что это медиана и она будет корнем, а остальные две вершины — её детьми. Т.е. расход памяти здесь — на хранение одной вершины, что согласуется с верхней оценкой для дерева из трёх вершин — &amp;lt;tex&amp;gt;log(3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
=== Удаление элемента ===&lt;br /&gt;
Удаляем элемент из дерева обычным удалением вершины бинарного дерева поиска (поиск элемента, удаление, возможное переподвешивание детей). &lt;br /&gt;
Далее проверяем выполнение условия:&amp;lt;br&amp;gt; &lt;br /&gt;
:&amp;lt;tex&amp;gt;size[T] &amp;lt; \alpha \cdot maxsize[T]&amp;lt;/tex&amp;gt;;&amp;lt;br&amp;gt;&lt;br /&gt;
Если оно выполняется — дерево могло потерять α-балансировку по весу, а значит нужно выполнить полную перебалансировку дерева (начиная с корня) и присвоить:&amp;lt;br&amp;gt;&lt;br /&gt;
:&amp;lt;tex&amp;gt;maxsize[T] = size[T]&amp;lt;/tex&amp;gt;;&amp;lt;br&amp;gt;&lt;br /&gt;
==Вопросы==&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
*'''Как пройти от вершины вверх к корню? Нам нужно хранить ссылки на родителей?'''&lt;br /&gt;
:Поскольку мы пришли к месту вставки новой вершины из корня дерева — у нас есть стек, в котором находится весь путь от корня к новой вершине. Берём родителей из него.;&lt;br /&gt;
*'''Как посчитать вес вершины — ведь он не хранится в самой вершине?'''&lt;br /&gt;
:Для новой вершины вес = 1. Для её родителя вес = 1 (вес новой вершины) + 1 (вес самого родителя) + &amp;lt;tex&amp;gt;size(brother(x))&amp;lt;/tex&amp;gt;.;&lt;br /&gt;
*'''Как посчитать &amp;lt;tex&amp;gt;size(brother(x))&amp;lt;/tex&amp;gt;?'''&lt;br /&gt;
:Рекурсивно. Это займёт время &amp;lt;tex&amp;gt;O(size(brother(x)))&amp;lt;/tex&amp;gt;. Понимая, что в худшем случае  придётся посчитать вес половины дерева — здесь появляется та самая сложность &amp;lt;tex&amp;gt;O(N)&amp;lt;/tex&amp;gt; в худшем случае, о которой говорилось в начале. Но поскольку мы обходим поддерево α-сбалансированного по весу дерева можно показать, что амортизированная сложность операции не превысит &amp;lt;tex&amp;gt;O(log N)&amp;lt;/tex&amp;gt;.;&lt;br /&gt;
*'''Что делать, если возникло несколько вершин, для которых нарушился α-балан?'''&lt;br /&gt;
:Ответ прост: выбрать можно любую.;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
==Внешние ссылки==&lt;br /&gt;
*[https://en.wikipedia.org/wiki/Tree_traversal#In-order_.28symmetric.29 In-order обход дерева]&lt;br /&gt;
==Источники информации==&lt;br /&gt;
*[https://en.wikipedia.org/wiki/Scapegoat_tree Википедия - Scapegoat tree]&amp;lt;br&amp;gt;&lt;br /&gt;
*[https://habrahabr.ru/company/infopulse/blog/246759/ Хабрахабр - Scapegoat деревья]&amp;lt;br&amp;gt;&lt;br /&gt;
*[https://people.ksp.sk/~kuko/gnarley-trees/ Scapegoat Tree Applet by Kubo Kovac]&lt;/div&gt;</summary>
		<author><name>Algo1s097</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%92%D0%B7%D0%B2%D0%B5%D1%88%D0%B5%D0%BD%D0%BD%D0%BE%D0%B5_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE&amp;diff=57141</id>
		<title>Взвешенное дерево</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%92%D0%B7%D0%B2%D0%B5%D1%88%D0%B5%D0%BD%D0%BD%D0%BE%D0%B5_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE&amp;diff=57141"/>
				<updated>2016-12-08T11:39:53Z</updated>
		
		<summary type="html">&lt;p&gt;Algo1s097: Новая страница: «== Определение == '''Scapegoat-дерево''' (англ. ''Scapegoat-Tree'') {{---}} сбалансированное бинарное дерево п...»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Определение ==&lt;br /&gt;
'''Scapegoat-дерево''' (англ. ''Scapegoat-Tree'') {{---}} сбалансированное бинарное дерево поиска, обеспечивающее наихудшее &amp;lt;tex&amp;gt;O(log N)&amp;lt;/tex&amp;gt; время поиска, и &amp;lt;tex&amp;gt;O(log N)&amp;lt;/tex&amp;gt; - амортизирующее время вставки и удаления элемента.&lt;br /&gt;
В отличие от большинства других самобалансирующихся бинарных деревьев поиска , которые обеспечивают худшем случае &amp;lt;tex&amp;gt;O(log N)&amp;lt;/tex&amp;gt; время поиска, Scapegoat деревья не требуют дополнительной памяти в узлах по сравнению с обычным двоичным деревом поиска : узел хранит только ключ и два указателя на своих потомков. &lt;br /&gt;
&lt;br /&gt;
== Достоинства Scapegoat дерева ==&lt;br /&gt;
# Отсутствие необходимости хранить какие-либо дополнительные данные в вершинах (а значит мы выигрываем по памяти у таких структур, как [[Красно-черное дерево]], [[АВЛ-дерево]] и [[Декартово дерево]])&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# Отсутствие необходимости перебалансировать дерево при операции поиска (а значит мы можем гарантировать максимальное время поиска &amp;lt;tex&amp;gt;O(log N)&amp;lt;/tex&amp;gt;, в отличии от структуры данных [[Splay-дерево]], где гарантируется только амортизированное &amp;lt;tex&amp;gt;O(log N)&amp;lt;/tex&amp;gt;)&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# Амортизированная сложность операций вставки и удаления &amp;lt;tex&amp;gt;O(log N)&amp;lt;/tex&amp;gt; — это в общем-то аналогично остальным типам деревьев&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# При построении дерева мы выбираем некоторый коэффициент «строгости» α, который позволяет улучшать дерево, делая операции поиска более быстрыми за счет замедления     операций модификации или наоборот. Можно реализовать структуру данных, а дальше уже подбирать коэффициент по результатам тестов на реальных данных и специфики использования дерева.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
== Недостатки Scapegoat дерева ==&lt;br /&gt;
# В худшем случае операции модификации дерева могут занять &amp;lt;tex&amp;gt;O(N)&amp;lt;/tex&amp;gt; времени (амортизированная сложность у них по-прежнему &amp;lt;tex&amp;gt;O(log N)&amp;lt;/tex&amp;gt;, но защиты от плохих случаев нет).&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
# Можно неправильно оценить частоту разных операций с деревом и ошибиться с выбором коэффициента α — в результате часто используемые операции будут работать долго, а редко используемые — быстро, что не очень хорошо.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
== Операции ==&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition=Бинарное дерево поиска называется '''сбалансированным по весу''', если половина вершин расположены слева от корня, а другая половина справа.&lt;br /&gt;
}}&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Введем обозначения:'''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Квадратные скобки в обозначениях означают, что мы храним это значение явно, а значит можем взять за время &amp;lt;tex&amp;gt;О(1)&amp;lt;/tex&amp;gt;. Круглые скобки означают, что значение будет вычисляться по ходу дела то есть память не расходуется, но зато нужно время на вычисление.&lt;br /&gt;
* &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; — обозначение дерева&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* &amp;lt;tex&amp;gt;root[T]&amp;lt;/tex&amp;gt; — корень дерева &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* &amp;lt;tex&amp;gt;left[x]&amp;lt;/tex&amp;gt; — левый сын вершины x&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* &amp;lt;tex&amp;gt;right[x]&amp;lt;/tex&amp;gt; — правый сын вершины x&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* &amp;lt;tex&amp;gt;brother(x)&amp;lt;/tex&amp;gt; — брат вершины х (вершина, которая имеет с х общего родителя)&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* &amp;lt;tex&amp;gt;depth(x)&amp;lt;/tex&amp;gt; — глубина вершины х. Это расстояние от неё до корня (количество ребер)&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* &amp;lt;tex&amp;gt;height(T)&amp;lt;/tex&amp;gt; — глубина дерева T. Это глубина самой глубокой вершины дерева T&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* &amp;lt;tex&amp;gt;size(x)&amp;lt;/tex&amp;gt; — вес вершины х. Это количество всех её дочерних вершин + 1 (она сама)&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* &amp;lt;tex&amp;gt;size[T]&amp;lt;/tex&amp;gt; — размер дерева T. Это количество вершин в нём (вес корня)&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* &amp;lt;tex&amp;gt;maxsize[T]&amp;lt;/tex&amp;gt; — максимальный размер дерева. Это максимальное значение, которое параметр &amp;lt;tex&amp;gt;size[T]&amp;lt;/tex&amp;gt; принимал с момента последней перебалансировки.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt; Если перебалансировка произошла только что, то &amp;lt;tex&amp;gt;maxsize[T] = size[T]&amp;lt;/tex&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:0ce162a62b624da8ba02233b4b254f23.png]]&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Синим цветом обозначены '''глубины''' вершин, а красным - их '''веса'''.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
В данном Scapegoat-дереве &amp;lt;tex&amp;gt;size[T] = 4&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;maxsize[T] \geqslant 4&amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
* Коэффициeнт α — это число в диапазоне от &amp;lt;tex&amp;gt;[0.5; 1)&amp;lt;/tex&amp;gt;, определяющее требуемую степень качества балансировки дерева. &lt;br /&gt;
&amp;lt;br&amp;gt;{{Определение&lt;br /&gt;
|definition=Некоторая вершина x называется &amp;quot;α-сбалансированной по весу&amp;quot;, если вес её левого сына меньше либо равен   &amp;lt;tex&amp;gt;\alpha \cdot size(x)&amp;lt;/tex&amp;gt; и вес ей правого сына меньше либо равен &amp;lt;tex&amp;gt;\alpha \cdot size(x)&amp;lt;/tex&amp;gt;.}} &lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
:&amp;lt;tex&amp;gt;size(left[x]) \leqslant \alpha  \cdot size(x)&amp;lt;/tex&amp;gt;;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
:&amp;lt;tex&amp;gt;size(right[x]) \leqslant \alpha \cdot size(x)&amp;lt;/tex&amp;gt;;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Перед тем как приступить к работе с деревом, мы выбираем параметр α в диапазоне &amp;lt;tex&amp;gt;[0.5; 1)&amp;lt;/tex&amp;gt;. Также заводим две переменные для хранения текущих значений &amp;lt;tex&amp;gt;size[T]&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;maxsize[T]&amp;lt;/tex&amp;gt; и обнуляем их.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
=== Поиск элемента ===&lt;br /&gt;
&amp;lt;br&amp;gt;Пусть мы хотим найти в данном Scapegoat дереве какой-то элемент. Применим стандартный алгоритм для двоичного дерева поиска - идем от корня, если значение в вершине равно значению искомого элемента, возвращаем, если значение в вершине меньше, то рекурсивно запускаемся от левого поддерева, если больше, то, соответственно, от левого.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Замечание:''' Дерево по ходу поиска искомой вершины ''не изменяется''.&amp;lt;br&amp;gt;&lt;br /&gt;
Сложность операции поиска зависит от коэффициента &amp;lt;tex&amp;gt;\alpha&amp;lt;/tex&amp;gt; и выражается формулой {{---}}  &amp;lt;tex&amp;gt;log&amp;lt;/tex&amp;gt;&amp;lt;sub&amp;gt;1/α&amp;lt;/sub&amp;gt;&amp;lt;tex&amp;gt;(N)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Таким образом, сложность получается логарифмическая, НО! При &amp;lt;tex&amp;gt;\alpha&amp;lt;/tex&amp;gt; близком к 0.5 мы получаем двоичный (или почти двоичный) логарифм, что означает практически идеальную  скорость поиска. При &amp;lt;tex&amp;gt;\alpha&amp;lt;/tex&amp;gt; близком к единице основание логарифма стремится к единице, а значит общая сложность стремится к &amp;lt;tex&amp;gt;O(N)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
=== Вставка элемента ===&lt;br /&gt;
Классический алгоритм вставки нового элемента: поиском ищем место, куда бы подвесить новую вершину, ну и подвешиваем. Легко понять, что это действие могло нарушить &amp;lt;tex&amp;gt;\alpha&amp;lt;/tex&amp;gt;-балансировку по весу для одной или более вершин дерева. И вот теперь начинается то, что и дало название нашей структуре данных: мы ищем  Scapegoat-вершину — вершину, для которой потерян &amp;lt;tex&amp;gt;\alpha&amp;lt;/tex&amp;gt;-баланс и её поддерево должно быть перестроено. Сама только что вставленная вершина, хотя и виновата в потере баланса, Scapegoat-вершиной  стать не может — у неё ещё нет потомков, а значит её баланс идеален. Соответственно, нужно пройти по дереву от этой вершины к корню, пересчитывая веса для каждой вершины по пути. Если на этом пути встретится вершина, для которой критерий &amp;lt;tex&amp;gt;\alpha&amp;lt;/tex&amp;gt;-сбалансированности по весу нарушился — мы полностью перестраиваем соответствующее ей поддерево так, чтобы восстановить &amp;lt;tex&amp;gt;\alpha&amp;lt;/tex&amp;gt;-сбалансированность по весу. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Сразу возникает вопрос {{---}} Как делать перебалансировку найденной Scapegoat-вершины?&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Есть 2 способа перебалансировки, {{---}} ниже  подробнее рассказывается о каждом из них.&lt;br /&gt;
====1 способ перебалансировки====&lt;br /&gt;
# Обходим всё поддерево Scapegoat-вершины (включая её саму) с помощью in-order обхода — на выходе получаем отсортированный список (свойство In-order обхода бинарного дерева поиска).&lt;br /&gt;
# Находим медиану на этом отрезке, подвешиваем её в качестве корня поддерева.&lt;br /&gt;
# Для «левого» и «правого» поддерева рекурсивно повторяем ту же операцию.&lt;br /&gt;
Данный способ требует  &amp;lt;tex&amp;gt;O(size(Scapegoat-root))&amp;lt;/tex&amp;gt; времени и столько же памяти.&lt;br /&gt;
====2 способ перебалансировки====&lt;br /&gt;
Мы вряд ли улучшим время работы перебалансировки — всё-таки каждую вершину нужно «подвесить» в новое место. Но мы можем попробовать сэкономить память. Давайте посмотрим на 1 способ алгоритма внимательнее. Вот мы выбираем медиану, подвешиваем в корень, дерево делится на два поддерева — и делится весьма однозначно. Никак нельзя выбрать «какую-то другую медиану» или подвесить «правое» поддерево вместо левого. Та же самая однозначность преследует нас и на каждом из следующих шагов. Т.е. для некоторого списка вершин, отсортированных в возрастающем порядке, у нас будет ровно одно порождённое данным алгоритмом дерево. А откуда же мы взяли отсортированный список вершин? Из in-order обхода изначального дерева. То есть каждой вершине, найденной по ходу in-order обхода перебалансируемого дерева соответствует одна конкретная позиция в новом дереве. И мы можем эту позицию рассчитать и без создания самого отсортированного списка. А рассчитав — сразу её туда записать. Возникает только одна проблема — мы ведь этим затираем какую-то (возможно ещё не просмотренную) вершину — что же делать? Хранить её. Где? Ответ прост: выделять для списка таких вершин память. Но этой памяти нужно будет уже не &amp;lt;tex&amp;gt;O(size(N))&amp;lt;/tex&amp;gt;, а всего лишь &amp;lt;tex&amp;gt;O(log N)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Представьте себе в уме дерево, состоящее из трёх вершин — корня и двух подвешенных как «левые» сыновья вершин. In-order обход вернёт нам эти вершины в порядке от самой «глубокой» до корня, но хранить в отдельной памяти по ходу этого обхода нам придётся всего одну вершину (самую глубокую), поскольку когда мы придём во вторую вершину, мы уже будем знать, что это медиана и она будет корнем, а остальные две вершины — её детьми. Т.е. расход памяти здесь — на хранение одной вершины, что согласуется с верхней оценкой для дерева из трёх вершин — &amp;lt;tex&amp;gt;log(3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
=== Удаление элемента ===&lt;br /&gt;
Удаляем элемент из дерева обычным удалением вершины бинарного дерева поиска (поиск элемента, удаление, возможное переподвешивание детей). &lt;br /&gt;
Далее проверяем выполнение условия:&amp;lt;br&amp;gt; &lt;br /&gt;
:&amp;lt;tex&amp;gt;size[T] &amp;lt; \alpha \cdot maxsize[T]&amp;lt;/tex&amp;gt;;&amp;lt;br&amp;gt;&lt;br /&gt;
Если оно выполняется — дерево могло потерять α-балансировку по весу, а значит нужно выполнить полную перебалансировку дерева (начиная с корня) и присвоить:&amp;lt;br&amp;gt;&lt;br /&gt;
:&amp;lt;tex&amp;gt;maxsize[T] = size[T]&amp;lt;/tex&amp;gt;;&amp;lt;br&amp;gt;&lt;br /&gt;
==Вопросы==&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
*'''Как пройти от вершины вверх к корню? Нам нужно хранить ссылки на родителей?'''&lt;br /&gt;
:Поскольку мы пришли к месту вставки новой вершины из корня дерева — у нас есть стек, в котором находится весь путь от корня к новой вершине. Берём родителей из него.;&lt;br /&gt;
*'''Как посчитать вес вершины — ведь он не хранится в самой вершине?'''&lt;br /&gt;
:Для новой вершины вес = 1. Для её родителя вес = 1 (вес новой вершины) + 1 (вес самого родителя) + &amp;lt;tex&amp;gt;size(brother(x))&amp;lt;/tex&amp;gt;.;&lt;br /&gt;
*'''Как посчитать &amp;lt;tex&amp;gt;size(brother(x))&amp;lt;/tex&amp;gt;?'''&lt;br /&gt;
:Рекурсивно. Это займёт время &amp;lt;tex&amp;gt;O(size(brother(x)))&amp;lt;/tex&amp;gt;. Понимая, что в худшем случае  придётся посчитать вес половины дерева — здесь появляется та самая сложность &amp;lt;tex&amp;gt;O(N)&amp;lt;/tex&amp;gt; в худшем случае, о которой говорилось в начале. Но поскольку мы обходим поддерево α-сбалансированного по весу дерева можно показать, что амортизированная сложность операции не превысит &amp;lt;tex&amp;gt;O(log N)&amp;lt;/tex&amp;gt;.;&lt;br /&gt;
*'''Что делать, если возникло несколько вершин, для которых нарушился α-балан?'''&lt;br /&gt;
:Ответ прост: выбрать можно любую.;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
==Внешние ссылки==&lt;br /&gt;
*[https://en.wikipedia.org/wiki/Tree_traversal#In-order_.28symmetric.29 In-order обход дерева]&lt;br /&gt;
==Источники информации==&lt;br /&gt;
*[https://en.wikipedia.org/wiki/Scapegoat_tree Википедия - Scapegoat tree]&amp;lt;br&amp;gt;&lt;br /&gt;
*[https://habrahabr.ru/company/infopulse/blog/246759/ Хабрахабр - Scapegoat деревья]&amp;lt;br&amp;gt;&lt;br /&gt;
*[https://people.ksp.sk/~kuko/gnarley-trees/ Scapegoat Tree Applet by Kubo Kovac]&lt;/div&gt;</summary>
		<author><name>Algo1s097</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:0ce162a62b624da8ba02233b4b254f23.png&amp;diff=56983</id>
		<title>Файл:0ce162a62b624da8ba02233b4b254f23.png</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:0ce162a62b624da8ba02233b4b254f23.png&amp;diff=56983"/>
				<updated>2016-12-05T12:25:18Z</updated>
		
		<summary type="html">&lt;p&gt;Algo1s097: Scapegoat дерево&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Scapegoat дерево&lt;/div&gt;</summary>
		<author><name>Algo1s097</name></author>	</entry>

	</feed>