90
правок
Изменения
Нет описания правки
{{Теорема|id=Теорема1|statement=Описание структуры==HAT состоит из главного массива указателей Если <tex>topG</tex> и ряда листьев {{---}} это <tex>leaf</tex> (так же одномерные массивыp,q), в которых хранятся элементы.Возможное число указателей в главном массиве и возможное число элементов в каждом листе равны между собой и являются степенями двойки. HAT зполняется элементами от самого малого листа к самому большому, при этом каждый лист заполняется слева направо.===Получение элемента по номеру===Благодаря использованию степеней двойки, мы можем эффективно находить элементы в HAT, используя поразрядные операции. Пусть размер главного массива и каждого листа будет равен <tex>2^{power}</tex>. '''int''' topIndex('''int''' j) - граф с вершинами, имеющими степени <font color=greenmath>// Получить номер указателя в основном массивеd_i</fontmath> '''return''' j >> power '''int''' leafIndex('''int''' j) , то <font color=greentex>// Получить номер листа</font> '''return''' j & (L(1 << powerG) - 1) '''int''' getHat('''int''' j) <font color=green>// Вернуть элемент HAT. Нет проверки на выход за пределы массива.</fonttex> '''return''' top[topIndex(j)][leafIndex(j)]Рассмотрим как происходит вычисление адреса на примере. Пусть у нас есть HAT с размером листа равным имеет <tex>4q</tex>, тогда для нашего случая вершин и <texmath>power = 2q_L</texmath> ребер, где<texmath>(4 q_L = -q + \frac{1}{2}\sum{d_{i}^{2)}}</tex>. Получим значения функций для элемент под номером <texmath>5</tex>: *|proof=По определению реберного графа граф <tex>topIndexL(5G)</tex> : в данном случае битовый сдвиг эквивалентен опреации деления (взятию по модулю) имеет <tex>jq</tex> на вершин. Каждые <math>2^{2}d_i</math>. То есть получим ребер, инцидентных вершине <texmath>1v_i</texmath>, дают вклад <math> \begin{pmatrix} d_i \\ 2 \end{---pmatrix}} действительно элемент под номером <tex>5</texmath> находится в первом листе (нумерция листов с <tex>0</tex>).*число ребер графа <tex>leafIndexL(5G)</tex> : в данном случае битовый сдвиг эквивалентен умножению , так что<texmath>q_L = \sum{\begin{pmatrix} d_i \\ 2 \end{pmatrix}} = \frac{1</tex> на <tex>}{2^}\sum{2d_i(d_i-1)}</tex>. Тоесть после вычитания <tex>= \frac{1</tex> получим число формата <tex>011..11</tex>, в нашем случае }{2}\sum{d_i^2}---\frac{1}{2} <tex>011</tex>. *<tex>5_\sum{10d_i} = 101_2 - 101</tex> <tex>\&</tex> <tex>011 = 001</tex>, то есть индекс в листе равен <tex>frac{1}{2}\sum{d_i^2-q}</texmath> (в листах нумерация так же с <tex>0</tex>).[[Файл:fullHAT.png|200px]]}}
===Добавление элементов=Построение==*Чаще всего при добавлении элемента в одном из листьев (последнем незаполненном на данный момент) найдется свободное место, что позволит осуществить быструю вставку {{---}} <math>O(1)</math>[[Файл:line_graph_build_1. *Реже мы столкнемся со случаем, когда необходимо создать новый лист. Достаточно всего лишь добавить указатель в свободную ячейку главного массива, что также позволит произвести вставку элемента за <math>O(1)</math>.*Самый интересный случай {{---}} когда главный массив и все листья заполнены. Cначала вычислим нужный размер (массивы <tex>top</tex> и <tex>leaf</tex> увеличиваются в <tex>2</tex> раза, то есть <math>power = power \cdot 2 </math>), затем скопируем элементы в новую структуру HAT, освобождая старые листья и распределяя новые листья(размер листа изменился, а значит количество элементов в листе и количество используемых листьев так же изменится).*Такой подход к расширению помогает избежать избыточного перекопирования, используемого во многих реализациях массивов переменной длины, потому что увеличения размеров всех массивов происходит редко (как будет видно ниже). Копировать элементы мы будем только тогда, когда главный массив полон (достигли соответствующей степени двойки, то есть <tex> N = (2 \cdot 2)^k</tex>, где <tex>k</tex> {{---}} натуральное число), тогда общая сумма перекопирования будет равна <math>1+4+16+64+256+...+N</math>. Воспользуемся тождествомpng|200px]][[Файл: <math>(x^{n+1} -1)=(x-1)(1+x+x^2+x^3+line_graph_build_2... + x^k)</math>, тогда для нашего случаяpng|200px]][[Файл: <math>1 +4+4^2+4^3+line_graph_build_3...+4^k = (4^{k+1} -1)/(4-1) = (4N-1)/3</math>, или около <math>4N/3</math>. Это означает, что среднее число дополнительных операций копирования {{---}} <math>O(N)</math> для последовательного добавления N элементов, а не <math>O(N^2)</math>. Мы получили <math>4N/3</math> против <math>2N</math> в обычном динамическом массиве, то есть константа уменьшилась.png|200px]][[Файл:AlgoF2line_graph_build_4.gifpng|400px200px]]
==Источники информации==
*[[wikipedia:enru:Hashed array tree Рёберный_граф | Wikipedia {{---}} Hashed array tree Реберные графы ]]*Cline, MХарари Фрэнк '''Теория графов''': Пер.Pс англ. and G/ Предисл.AВ. Lomow, C++ FAQs, Reading, MA: Addison-Wesley, 1995П. *Cormen, TКозырева; Под ред.HГ., CП.EГаврилова. Leiserson, and RИзд.L4-е. Rivest— М. Introduction to Algorithms, Cambridge, MA: MIT PressКнижный дом "ЛИБРОКОМ", 19902009. — 296 с. — ISBN 978-5-397-00622-4.