СНМ (реализация с помощью леса корневых деревьев) — различия между версиями
Nook (обсуждение | вклад) |
|||
Строка 1: | Строка 1: | ||
− | |||
− | |||
==Реализация== | ==Реализация== | ||
Каждое множество хранится в виде дерева. Элементы множества хранятся в узлах дерева. У каждого множества есть его представитель {{---}} один из элементов этого множества, он хранится в корне дерева. В каждом узле, кроме корня, хранится ссылка на "родителя". | Каждое множество хранится в виде дерева. Элементы множества хранятся в узлах дерева. У каждого множества есть его представитель {{---}} один из элементов этого множества, он хранится в корне дерева. В каждом узле, кроме корня, хранится ссылка на "родителя". | ||
Строка 14: | Строка 12: | ||
===Сжатие пути=== | ===Сжатие пути=== | ||
− | Эта эвристика несколько модифицирует операцию ''get''. Операция get вызывается для элемента ''x'', проходит через несколько вершин и попадает в корень. Все пройденные в этом процессе вершины принадлежат тому же множеству, что и ''x''. Поэтому | + | Эта эвристика несколько модифицирует операцию ''get''. Операция get вызывается для элемента ''x'', проходит через несколько вершин и попадает в корень. Все пройденные в этом процессе вершины принадлежат тому же множеству, что и ''x''. Поэтому мы можем подвесить (изменить ссылки) эти вершины напрямую к корню дерева и, таким образом, уменьшить его высоту. При нерекурсивной реализации операция ''get'' становится двухпроходной. |
===Псевдокод=== | ===Псевдокод=== |
Версия 23:05, 26 марта 2012
Содержание
Реализация
Каждое множество хранится в виде дерева. Элементы множества хранятся в узлах дерева. У каждого множества есть его представитель — один из элементов этого множества, он хранится в корне дерева. В каждом узле, кроме корня, хранится ссылка на "родителя".
При объединении двух множеств, корень одного дерева подвешивается к другому (операция union). Таким образом, чтобы определить, в каком множестве находится элемент достаточно пройтись по ссылкам по дереву вверх до корня (операция get).
Без использования дополнительных "улучшений", такое дерево может выродиться в линейный список, где get будет работать за линейное время, и никакого выигрыша по сравнению с наивными реализацими не будет. Выигрыш в скорости можно получить, используя две эвристики: объединение по рангу (union by rank) и сжатие пути (path compression).
Объединение по рангу
Эта эвристика аналогична весовой эвристике у связных списков. Идея в том, чтобы при объединении подвешивать дерево с меньшей глубиной к дереву с большей.
Вместо того, чтобы явно хранить высоту дерева, можно хранить его ранг, который по сути является некой верхней оценкой высоты дерева. У дерева, состоящего ровно из одного элемента ранг равен 1. При объединении дерево с меньшим рангом подвешивается к дереву с большим, и ранг объединенного дерева становится равным большему из этих двух рангов. Если ранги объединяемых деревьев равны, то не важно какое к какому дереву подвешивать, но ранг объединенного дерева следует делать большим на 1.
Сжатие пути
Эта эвристика несколько модифицирует операцию get. Операция get вызывается для элемента x, проходит через несколько вершин и попадает в корень. Все пройденные в этом процессе вершины принадлежат тому же множеству, что и x. Поэтому мы можем подвесить (изменить ссылки) эти вершины напрямую к корню дерева и, таким образом, уменьшить его высоту. При нерекурсивной реализации операция get становится двухпроходной.
Псевдокод
Для реализации СНМ будем поддерживать следующие массивы:
— массив "родителей".
— массив рангов.
get
get(x) if p[x] != x p[x] = get(p[x]) return p[x]
union
union(x, y) x = get(x) y = get(y) if x == y return; if r[x] == r[y] r[x]++ if r[x] < r[y] p[x] = y else p[y] = x
Асимптотика
- см. также Анализ реализации с ранговой эвристикой
Операция | Истинное время | Амортизированное время |
---|---|---|
get | ||
union |
- m — общее количество операций
- n — полное количество элементов
- — функция, обратная к функции Аккермана (если операций get и элементов).
Функция Аккермана
Функция Аккермана определяется следующим рекуррентным соотношением для целых неотрицательных чисел
и :
Таблица значений функции Аккермана:
0 | 1 | 2 | 3 | 4 | 5 | |
---|---|---|---|---|---|---|
1 | 1 | 2 | 4 | 8 | 16 | 32 |
2 | 2 | 4 | 16 | 65536 | ||
3 | 2 | 16 | ||||
4 | 2 |
Функция, обратная функции Аккермана —
. Как видно из таблицы значений для функции Аккермана, обратная функции для всех мыслимых значений не превышает 4, то есть можно считать, что операция get выполняется за константное время.Ссылки
- Система непересекающихся множеств — описание этой реализации на habrahabr.ru
- Функция Аккермана — Википедия
Литература
- Томас Кормен, Чарльз Лейзерсон, Рональд Ривест, Клиффорд Штайн. Алгоритмы. Построение и анализ — Вильямс, 2010. - 1296с. — ISBN 978-5-8459-0857-4, 0-07-013151-1. (стр 589)