Изменения

Перейти к: навигация, поиск

Толстая куча на избыточном счётчике

561 байт убрано, 23:52, 31 января 2019
м
Дмитрий Мурзин переименовал страницу Толстая куча на избыточном счетчике в Толстая куча на избыточном счётчике: Ёфикация
|neat = 1
|definition=
Определяем '''толстое дерево''' (англ. ''Thick tree'') <tex>F_k</tex> ранга <tex>k ~(k = 0, 1, 2 ~,\dots ldots )</tex> следующим образом:
*Толстое дерево <tex>F_0</tex> ранга ноль состоит из единственного узла. <br>
*Толстое дерево <tex>F_k</tex> ранга <tex>k</tex>, для <tex>k = 1, 2, 3,\dots ldots </tex>, состоит из трех деревьев <tex>F_{k-1}</tex> ранга <tex>k-1</tex>,таких, что корни двух из них являются самыми левыми потомками корня третьего.
}}
[[Файл:FatTreesExampleFatHeap.png |400px|thumb|center|Пример толстых деревьев <tex>F_0, F_1, F_2, F_3</tex>]]
{{Определение
Толстый лес из <tex>n</tex> узлов содержит <tex>O(n\log{n})</tex> деревьев.
|proof=
}}
 
{{Определение
|id=def2
|neat =
|definition=
'''Лес''' будем называть '''нагруженным''', если он состоит из нескольких толстых деревьев, ранги которых не обязательно попарно различны и узлам которых взаимно однозначно поставлены в соответствие элементы взвешенного множества.
}}
{{Определение
|id=def3
|neat =
|definition=
'''Узел''' (англ. ''Node'') в ''нагруженном лесе'' назовем '''неправильным''', если его ключ меньше ключа его родителя.
}}
{{Определение
|id=def4
|neat =
|definition=
'''Нагруженный лес''' назовем '''почти кучеобразным''', если для каждого значения <tex>k</tex> в нем имеется не более двух '''неправильных''' узлов ранга <tex>k</tex>.
}}
|neat =
|definition=
'''Избыточным''' <tex>b</tex>-арным представлением числа <tex>x</tex> будем называть последовательность <tex>d = d_n, d_{n-1}, ... \ldots, d_0</tex>, такую что<tex dpi = "150120">x = {\sum\limits^{n}_{i = 0} {d_i}}{b^i}</tex>
где <tex> d_i \in \{0, 1, ...\ldots, b\} </tex>, <tex> i \in \{0, 1, ...\ldots, n\} </tex>
}}
|neat =
|definition=
Пусть <tex>L(i)</tex> — номер разряда, отличного от <tex>b-1</tex> и ближайшего слева от <tex>i</tex>-го разряда в регулярном <tex>b</tex>-арном избыточном представлении <tex>d = d_n, ... \ldots, d_0</tex>.
<br>
Определим '''Прямой указатель''' <tex>L'(i)</tex> определим следующим образом:
*<tex>L'(i) = L(i)</tex> , если <tex>d_i \in \{b-1, b-2\}</tex> и <tex>d(L(i))=b</tex>;
*<tex>L'(i)</tex> — произвольное число <tex>>i</tex>, если <tex>d_i \in \{b-1, b-2\}</tex> и <tex>d(L(i))<b-1</tex>;
*<tex>L'(i)</tex> — не определено, если <tex>d \notin \{b-1, b-2 \}</tex> .
<br>
Величину <tex>L'(i)</tex> будем называть прямым указателем.
}}
===Фиксация цифры===
Фиксацией цифры <tex>b</tex>, стоящей в <tex>i</tex>-м разряде представления <tex>d</tex>, назовем операцию <tex>\mathrm{fix(i)}</tex>, заключающуюся в обнулении цифры <tex>d_i</tex> и инкрементировании цифры <tex> d_{i+1} </tex>, при этом если <tex>i=n</tex> , то полагаем <tex>d_{i+1} = 1</tex>. При каждом выполнении операции фиксации будем обновлять значение <tex>L'(i)</tex>. Очевидно, при <tex>b>2</tex> операцию <tex>\mathrm{fix(i)}</tex> можно выполнить следующим образом:
'''void''' fix('''int''' i):
'''if''' d[i] == b
d[i] = 0
===Инкремент===
Операцию <tex>\mathrm{inc(i)}</tex> инкрементирования <tex>i</tex>-й цифры избыточного представления <tex>d</tex> можно выполнить так:
'''void''' inc('''int''' i):
fix(i)
'''if''' (d[i] == b - 1) '''or''' (d[i] == b - 2)
===Обновление прямого указателя===
Обновление прямого указателя <tex>i</tex>-го разряда корневого счетчика заключается в выполнении следующего псевдокода:
'''void''' updateForwardPionter('''int''' i):
'''if''' rootCount[i + 1].Value == 3 - 1
rootCount[i].forwardPointer = rootCount[i + 1].forwardPointer
===Корректировка при вставке ===
Корректировка списочной части <tex>i</tex>-го разряда корневого счетчика при вставке в кучу нового дерева ранга <tex>i~(\mathrm{insertTree(i,p)})</tex>. Эта процедура вставляет новое дерево ранга <tex>i</tex> (на него указывает указатель <tex>p</tex>) в списочную часть <tex>i</tex>-го разряда корневого счетчика <tex>\mathtt{rootCount}</tex> выглядит так: '''void''' insertTree('''int''' i, '''Node''' p):
p1 = rootCount[i].listPointer
'''if''' rootCount[i].Value <tex> \ne </tex> 0
===Корректировка при удалении===
Корректировка списочной части <tex>i</tex>-го разряда корневого счетчика при удалении из кучи дерева ранга <tex>i~(\mathrm{deleteTree(i,p)})</tex>. Эта процедура удаляет дерево ранга <tex>i</tex> (на него указывает указатель <tex>p</tex>) из списочной части <tex>i</tex>-го разряда корневого счетчика <tex>\mathtt{rootCount}</tex> . Будем считать, что указанное дерево присутствует в куче. Процедура заключается в выполнении следующего псевдокода:
'''void''' deleteTree('''int''' i, '''Node''' p):
p1 = rootCount[i].listPointer
'''if''' p1 == p
rootCount[i].listPointer = p.right
j = 1
'''while''' (j <tex> \le leqslant </tex> rootCount[i].Value) '''and''' (p1.right <tex> \ne </tex> p):
j++
p1 = p1.right
'''Связывание''' <tex>\mathrm{fastening (p1, p2, p3)}</tex> трех толстых деревьев ранга <tex>i</tex> в одно толстое дерево ранга <tex>i+1</tex>. Эта функция принимает три указателя <tex>p1, p2 ,p3</tex> на три разных толстых дерева одного и того же ранга <tex>i</tex> и возвращает указатель на вновь сформированное дерево ранга <tex>i+1</tex> .
Процедура заключается в выполнении следующего псевдокода:
'''Node''' fastening ('''Node''' p1, '''Node''' p2, '''Node''' p3): '''if''' (p1.key <tex> \le leqslant </tex> p2.key) '''and''' (p1.Key <tex> \le leqslant </tex> p3.key)
minP = p1
p1 = p2
p2 = p3
'''if''' (p2.key <tex> \le leqslant </tex> p1.key) '''and''' (p2.key <tex> \le leqslant </tex> p3.key)
minP = p2
p1 = p1
p2 = p3
'''if''' (p3.key <tex> \le leqslant </tex> p1.key) '''and''' (p3.key <tex> \le leqslant </tex> p2.key)
minP = p3
p1 = p1
Функция <tex>\mathrm{getKey(p)}</tex> по указателю p на элемент определяет значение его ключа:
<font color=green>//под <tex>\infty</tex> нужно понимать нейтральный относительно минимума элемент.</font>
'''int''' getKey('''Node''' p):
'''if''' p == NULL
min = <tex>\infty</tex>
Функция <tex>\mathrm{minKeyNodeRoot(p)}</tex>, которая по указателю <tex>p</tex> на списочную часть разряда корневого счетчика возвращает указатель на корневой узел с минимальным ключом:
'''Node''' minKeyNodeRoot('''Node''' p):
p1 = p
minP = p1
===Операция фиксации ===
Операция фиксации <tex>\mathrm{rmFixRootCount(i)}</tex> для <tex>i</tex>-го разряда корневого счетчика подразумевает, что его значение равно трем, а списочная часть содержит указатель на список деревьев ранга <tex>i</tex>, состоящий ровно из трех деревьев. При выполнении этой операции значение в <tex>i</tex>-м разряде — должно стать равным нулю, а значение в <tex>i</tex>-м разряде увеличиться на единицу. То есть в куче не должно остаться деревьев ранга <tex>i</tex>, а количество деревьев ранга <tex>i+1</tex> должно увеличиться на единицу. Для этого следует удалить из кучи три присутствующих в ней дерева ранга <tex>i</tex> , связать их в дерево ранга <tex>i+1</tex> и вставить вновь полученное дерево в кучу.
Следует учесть, что ранг нового дерева может стать больше, чем <tex>\mathtt{maxRank}</tex>, что потребует инициализации нового разряда. Для этого необходимо увеличить значение <tex>\mathtt{maxRank}</tex> на единицу и заполнить новое поле, а также провести инициализацию нового разряда. '''void''' rmFixRootCount('''int''' i)
'''if''' maxRank == i
maxRank = i + 1
===Инкрементирование i-го разряда корневого счетчика===
По сравнению с описанным алгоритмом инкрементирования <tex>i</tex>-го разряда избыточного представления здесь мы должны учесть работу со списочной частью и обновить прямые указатели.
'''void''' rmIncRootCount('''int''' i,'''Node''' p)
'''if''' (rootCount[i].Value == 1) '''or''' (rootCount[i].Value == 2)
'''if''' rootCount[rootCount[i].forwardPointer].Value == 3
===Удаление дерева из кучи===
Процедура удаления дерева из кучи подразумевает наличие в куче этого дерева. Пусть удаляемое дерево имеет ранг <tex>i</tex> . Тогда значение <tex>i</tex>-го разряда избыточного корневого представления не равно нулю. То есть уменьшение этого значения на единицу не испортит регулярности представления и не потребует обновления каких-либо указателей. Необходимо лишь соответствующим образом обработать списочную часть.
'''void''' delete('''int''' i, '''Node''' p):
deleteTree(i, p)
rootCount[i].Value = rootCount[i].Value - 1
===Нахождение дерева с минимальным ключом в корне <tex>\mathrm{minKey()}</tex>===
'''Node''' minKey()
minP = NULL
'''for''' i = 0 to maxRank:
'''Счетчик нарушений''' представлен [[Саморасширяющийся массив|саморасширяющимся массивом]], элементы которого состоят из четырех полей:
*<tex>\mathtt{countViolation[i].Value}</tex> {{---}} количество неправильных узлов ранга <tex>i</tex> в куче.*<tex>\mathtt{countViolation[i].forvardPointer}</tex> {{---}} прямой указатель <tex>i</tex>-го разряда*<tex>\mathtt{countViolation[i].firstViolation}</tex> {{---}} указатель на неправильный узел ранга <tex>i</tex>*<tex>\mathtt{countViolation[i].secondViolation}</tex> {{---}} указатель на неправильный узел ранга <tex>i</tex>
{{Утверждение
}}
Для '''инициализации''' нового звена в счетчике нарушений необходимо лишь занулить его значение в новом разряде. Делается это только тогда, когда мы вводим в кучу новое дерево ранга <tex>\mathtt{maxRank + 1}</tex>. Это первый момент появления в куче узла ранга <tex>\mathtt{maxRank + 1}</tex>. Для тех нарушений, которые могут возникнуть в узлах ранга меньше либо равного <tex>\mathtt{maxRank + 1}</tex>, соответствующие разряды счетчика нарушений уже инициализированы, а узлов большего ранга в куче пока нет.
==Основные операции==
===deleteViolation===
Для освобождения кучи от нарушений достаточно выполнить следующий псевдокод:
'''void''' deleteViolation('''Node''' h2):
'''for''' i = 0 '''to''' h2.maxRank
'''if''' countViolation[i].Value == 2
fixCountViolation(i)
==См. также==* [[Тонкая куча]] ==Источникиинформации==
* [http://www.intuit.ru/studies/courses/100/100/lecture/2935?page=1 INTUIT.ru {{---}} Толстые кучи]
* [https://www.lektorium.tv/lecture/14234 CS center {{---}} Приоритетные очереди]
[[Категория: Дискретная математика и алгоритмы]]
[[Категория: Приоритетные очереди]]
[[Категория: Структуры данных]]

Навигация