<?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=185.129.100.186&amp;*</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=185.129.100.186&amp;*"/>
		<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/185.129.100.186"/>
		<updated>2026-08-19T01:08:05Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A5%D0%B5%D1%88%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%BA%D1%83%D0%BA%D1%83%D1%88%D0%BA%D0%B8&amp;diff=72071</id>
		<title>Хеширование кукушки</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A5%D0%B5%D1%88%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%BA%D1%83%D0%BA%D1%83%D1%88%D0%BA%D0%B8&amp;diff=72071"/>
				<updated>2019-12-26T15:17:25Z</updated>
		
		<summary type="html">&lt;p&gt;185.129.100.186: /* Плюсы и минусы алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:cuckoo.png|thumb|Пример хеширования кукушки. Стрелки показывают второе возможное место элементов. Если нам надо будет вставить новый элемент на место А, то мы поместим А в его вторую ячейку, занятую В, а В переместим в его вторую ячейку, которая сейчас свободна. А вот помещение нового элемента на место Н не получится: так как Н — часть цикла, добавленный элемент будет вытеснен после прохода по циклу.]]&lt;br /&gt;
&lt;br /&gt;
'''Хеширование кукушки'''(англ. ''Cuckoo hashing'') {{---}} один из способов [[Разрешение коллизий|борьбы с коллизиями]] при создании [[Хеш-таблица|хеш-таблицы]].&lt;br /&gt;
&lt;br /&gt;
==Алгоритм==&lt;br /&gt;
&lt;br /&gt;
Основная идея хеширования кукушки — использование двух хеш-функций вместо одной (далее &amp;lt;tex&amp;gt;h_1(x)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;h_2(x)&amp;lt;/tex&amp;gt;). Также есть вариант алгоритма, в котором используются две хеш-таблицы, и первая хеш-функция указывает на ячейку из первой таблицы, а вторая — из второй. Рассмотрим алгоритмы функций &amp;lt;tex&amp;gt;add(x), remove(x)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;contains(x)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Выберем &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; хэш-функции &amp;lt;tex&amp;gt;h_1(x)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;h_2(x)&amp;lt;/tex&amp;gt; (из [[Универсальное семейство хеш-функций | универсального семейства хэш-функций]]).&lt;br /&gt;
&lt;br /&gt;
===='''Add'''==== &lt;br /&gt;
Добавляет элемент с ключом &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; в хэш-таблицу&lt;br /&gt;
&lt;br /&gt;
# Если одна из ячеек с индексами &amp;lt;tex&amp;gt;h_1(x)&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;h_2(x)&amp;lt;/tex&amp;gt; свободна, кладем в нее элемент. &lt;br /&gt;
# Иначе произвольно выбираем одну из этих ячеек, запоминаем элемент, который там находится, помещаем туда новый.&lt;br /&gt;
# Смотрим в ячейку, на которую указывает другая хеш-функция от элемента, который запомнили, если она свободна, помещаем его в нее. &lt;br /&gt;
# Иначе запоминаем элемент из этой ячейки, кладем туда старый. Проверяем, не зациклились ли мы.&lt;br /&gt;
# Если не зациклились, то продолжаем данную процедуру поиска свободного места пока не найдем свободное место или зациклимся.&lt;br /&gt;
# Иначе выбираем &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; новые хеш-функции и перехешируем все добавленные элементы.&lt;br /&gt;
# Так же после добавления нужно увеличить размер таблицы в случае если она заполнена.&lt;br /&gt;
&lt;br /&gt;
===='''Remove'''====&lt;br /&gt;
Удаляет элемент с ключом &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; из хэш-таблицы.&lt;br /&gt;
&lt;br /&gt;
# Смотрим ячейки с индексами &amp;lt;tex&amp;gt;h_1(x)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;h_2(x)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Если в одной из них есть искомый элемент, просто помечаем эту ячейку как свободную.&lt;br /&gt;
&lt;br /&gt;
===='''Contains'''====&lt;br /&gt;
Проверяет на наличие элемента &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; в хэш-таблице&lt;br /&gt;
&lt;br /&gt;
# Смотрим ячейки с индексами &amp;lt;tex&amp;gt;h_1(x)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;h_2(x)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Если в одной из них есть искомый элемент, возвращаем true.&lt;br /&gt;
# Иначе возвращаем false.&lt;br /&gt;
&lt;br /&gt;
== Зацикливание ==&lt;br /&gt;
&lt;br /&gt;
Зацикливание может возникнуть при добавлении элемента. Пусть мы добавляем элемент &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;. И обе ячейки &amp;lt;tex&amp;gt;h_1(x)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;h_2(x)&amp;lt;/tex&amp;gt; заняты. Элемент &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; положили изначально в ячейку &amp;lt;tex&amp;gt;h_i(x)&amp;lt;/tex&amp;gt;. Если в ходе перемещений элементов в таблице на очередном шаге мы опять хотим переместить элемент &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; в ячейку &amp;lt;tex&amp;gt;h_i(x)&amp;lt;/tex&amp;gt;, чтобы в ячейку &amp;lt;tex&amp;gt;h_j(x) ~(i \ne j) &amp;lt;/tex&amp;gt; мы смогли поместить какой-то &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt; (это может произойти, если в ходе перемещений элемент &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; был перемещен в ячейку &amp;lt;tex&amp;gt;h_j(x)&amp;lt;/tex&amp;gt;), то произошло зацикливание.&lt;br /&gt;
&lt;br /&gt;
Например, зацикливание возникнет, если добавить в хэш-таблицу &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt; элемента &amp;lt;tex&amp;gt;x,y,z&amp;lt;/tex&amp;gt; у которых &amp;lt;tex&amp;gt;h_1(x)=h_1(y)=h_1(z)&amp;lt;/tex&amp;gt;  и &amp;lt;tex&amp;gt;h_2(x)=h_2(y)=h_2(z)&amp;lt;/tex&amp;gt; .&lt;br /&gt;
&lt;br /&gt;
Одним из способов решения проблемы зацикливания является смена хэш-функции, что было доказано Джоном Трампом&amp;lt;ref&amp;gt;https://eprint.iacr.org/2014/059.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Время работы алгоритма==&lt;br /&gt;
&lt;br /&gt;
Удаление и проверка происходят за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt; (что является основной особенностью данного типа хеширования), добавление в среднем происходит за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;. Первые два утверждения очевидны: требуется проверить всего лишь &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; ячейки таблицы. &lt;br /&gt;
&lt;br /&gt;
{{ Утверждение&lt;br /&gt;
|id = Cuckoo_hashing add&lt;br /&gt;
|statement = Добавление в среднем происходит за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;. &lt;br /&gt;
|proof = Один из способов доказательства данного утверждения использует теорию случайных графов. Это делается через неориентированный &amp;quot;кукушкин граф&amp;quot;, где каждой ячейке хеш-таблицы соответствует ровно одна вершина, а каждому добавленному элементу — ребро с концами в вершинах, соответствующих ячейкам, в которые указывают хеш-функции элемента. При этом элемент будет добавлен без перехеширования тогда и только тогда, когда после добавления нового ребра граф будет оставаться псевдолесом, то есть каждая его компонента связности будет содержать не более одного цикла.&lt;br /&gt;
}}&lt;br /&gt;
Таким образом хеширование кукушки является одним из самых быстрых способов хеширования.&lt;br /&gt;
&lt;br /&gt;
==Плюсы и минусы алгоритма==&lt;br /&gt;
&lt;br /&gt;
Есть другие алгоритмы, которые используют несколько хеш-функций, в частности [[Фильтр Блума|фильтр Блума]], эффективная по памяти структура данных для нечётких множеств. Альтернативная структура данных для задач с теми же нечёткими множествами, основанная на кукушкином хешировании, называемая кукушкиным фильтром, использует даже меньшую память и (в отличие от классических фильтров Блума) позволяет удаление элемента, не только вставку и проверку существования. Однако теоретический анализ этих методов проведён существенно слабее, чем анализ фильтров Блума&amp;lt;ref&amp;gt;''Bin Fan, Michael Kaminsky, David Andersen'' Cuckoo Filter: Better Than Bloom // ;login:. — USENIX, 2013. — Т. 38, вып. 4. — С. 36–40.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Исследования, проведённые Жуковским, Хеманом и Бонзом&amp;lt;ref&amp;gt;''Marcin Zukowski, Sandor Heman, Peter Boncz'' Architecture-Conscious Hashing. — Proceedings of the International Workshop on Data Management on New Hardware (DaMoN), 2006.&amp;lt;/ref&amp;gt;, показали, что кукушкино хеширование существенно быстрее метода цепочек для малых хеш-таблиц, находящихся в кэше современных процессоров. Кеннет Росс&amp;lt;ref&amp;gt;''Kenneth Ross'' Efficient Hash Probes on Modern Processors. — IBM Research Report RC24100, 2006.&amp;lt;/ref&amp;gt; показал блочную версию кукушкиного хеширования (блок содержит более одного ключа), который работает быстрее обычных методов для больших хеш-таблиц в случае высокого коэффициента загрузки. Скорость работы блочной версии кукушкиной хеш-таблицы позднее исследовал Аскитис по сравнению с другими схемами хэширования.&lt;br /&gt;
&lt;br /&gt;
Обзор Мутцемахера&amp;lt;ref&amp;gt;''M. Mitzenmacher.'' Proceedings of of the 17th Annual European Symposium on Algorithms (ESA). — 2009.&amp;lt;/ref&amp;gt; представляет открытые проблемы, связанные с кукушкиным хешированием.&lt;br /&gt;
&lt;br /&gt;
Самый большой минуc {{---}} потраченная память. Чтобы гарантировать &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; по времени, нужно чтобы пары ключ/значение занимали не более &amp;lt;tex&amp;gt;50\%&amp;lt;/tex&amp;gt; памяти, потому что вытеснение старых элементов становится трудоемким. Также, добавление каждой новой хеш-функции значительно увеличивает среднюю скорость заполнения таблицы.&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Хеш-таблица]]&lt;br /&gt;
* [[Разрешение коллизий]]&lt;br /&gt;
* [[Идеальное хеширование]]&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Cuckoo_hashing Wikipedia — Cuckoo hashing]&lt;br /&gt;
* [http://www.cs.cmu.edu/afs/cs.cmu.edu/project/aladdin/wwwlocal/hash/PaRo01.pdf Cuckoo hashing — Pagh, Rasmus; Rodler, Flemming Friche (2001) (PDF, PS)]&lt;br /&gt;
&lt;br /&gt;
== Примеры ==&lt;br /&gt;
* [https://github.com/efficient/libcuckoo Concurrent high-performance Cuckoo hashtable written in C++]&lt;br /&gt;
* [http://sourceforge.net/projects/cuckoo-cpp/ Cuckoo hash map written in C++]&lt;br /&gt;
* [http://www.theiling.de/projects/lookuptable.html Static cuckoo hashtable generator for C/C++]&lt;br /&gt;
* [https://github.com/joacima/Cuckoo-hash-map/blob/master/CuckooHashMap.java Generic Cuckoo hashmap in Java]&lt;br /&gt;
* [http://hackage.haskell.org/packages/archive/hashtables/latest/doc/html/Data-HashTable-ST-Cuckoo.html Cuckoo hash table written in Haskell]&lt;br /&gt;
* [https://github.com/salviati/cuckoo Cuckoo hashing for Go]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Хеширование]]&lt;/div&gt;</summary>
		<author><name>185.129.100.186</name></author>	</entry>

	</feed>