<?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=37.214.24.12&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=37.214.24.12&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/37.214.24.12"/>
		<updated>2026-04-15T10:12:23Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A0%D0%B0%D0%B7%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BA%D0%BE%D0%BB%D0%BB%D0%B8%D0%B7%D0%B8%D0%B9&amp;diff=81273</id>
		<title>Разрешение коллизий</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A0%D0%B0%D0%B7%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BA%D0%BE%D0%BB%D0%BB%D0%B8%D0%B7%D0%B8%D0%B9&amp;diff=81273"/>
				<updated>2021-12-01T18:00:59Z</updated>
		
		<summary type="html">&lt;p&gt;37.214.24.12: Исправил неправильную табуляцию в псевдокоде&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Разрешение [[Хеш-таблица|коллизий]]''' (англ. collision resolution) в [[Хеш-таблица|хеш-таблице]], задача, решаемая несколькими способами: метод цепочек, открытая адресация и т.д. Очень важно сводить количество коллизий к минимуму, так как это увеличивает время работы с хеш-таблицами. &lt;br /&gt;
&lt;br /&gt;
== Разрешение коллизий с помощью цепочек ==&lt;br /&gt;
[[Файл:open_hash.png|thumb|380px|right|Разрешение коллизий при помощи цепочек.]]&lt;br /&gt;
Каждая ячейка &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; массива &amp;lt;tex&amp;gt;H&amp;lt;/tex&amp;gt; содержит указатель на начало [[Список|списка]] всех элементов, хеш-код которых равен &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;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(n)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Время работы поиска в наихудшем случае пропорционально длине списка, а если все &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; ключей захешировались в одну и ту же ячейку (создав список длиной &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;) время поиска будет равно &amp;lt;tex&amp;gt;\Theta(n)&amp;lt;/tex&amp;gt; плюс время вычисления хеш-функции, что ничуть не лучше, чем использование связного списка для хранения всех &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов.&lt;br /&gt;
&lt;br /&gt;
Удаления элемента может быть выполнено за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, как и вставка, при использовании двухсвязного списка.&lt;br /&gt;
&lt;br /&gt;
== Линейное разрешение коллизий ==&lt;br /&gt;
[[Файл:close_hash.png|thumb|380px|right|Пример хеш-таблицы с открытой адресацией и линейным пробированием.]]&lt;br /&gt;
Все элементы хранятся непосредственно в хеш-таблице, без использования связных списков. В отличие от хеширования с цепочками, при использовании этого метода может возникнуть ситуация, когда хеш-таблица окажется полностью заполненной, следовательно, будет невозможно добавлять в неё новые элементы. Так что при возникновении такой ситуации решением может быть динамическое увеличение размера хеш-таблицы, с одновременной её перестройкой.&lt;br /&gt;
&lt;br /&gt;
=== Стратегии поиска ===&lt;br /&gt;
&lt;br /&gt;
''' Последовательный поиск '''&lt;br /&gt;
&lt;br /&gt;
При попытке добавить элемент в занятую ячейку &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; начинаем последовательно просматривать ячейки &amp;lt;tex&amp;gt;i+1, i+2, i+3&amp;lt;/tex&amp;gt; и так далее, пока не найдём свободную ячейку. В неё и запишем элемент.&lt;br /&gt;
&lt;br /&gt;
[[Файл:hashtables1.png|400px|Последовательный поиск, частный случай линейного поиска.]]&lt;br /&gt;
&lt;br /&gt;
''' Линейный поиск '''&lt;br /&gt;
&lt;br /&gt;
Выбираем шаг &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt;. При попытке добавить элемент в занятую ячейку &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; начинаем последовательно просматривать ячейки &amp;lt;tex&amp;gt;i+(1 \cdot q), i+(2 \cdot q), i+(3 \cdot q)&amp;lt;/tex&amp;gt; и так далее, пока не найдём свободную ячейку. В неё и запишем элемент.&lt;br /&gt;
По сути последовательный поиск - частный случай линейного, где &amp;lt;tex&amp;gt;q=1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Hashtables56.PNG|400px|Линейный поиск с шагом q.]]&lt;br /&gt;
&lt;br /&gt;
''' Квадратичный поиск '''&lt;br /&gt;
&lt;br /&gt;
Шаг &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; не фиксирован, а изменяется квадратично: &amp;lt;tex&amp;gt;q = 1,4,9,16...&amp;lt;/tex&amp;gt;. Соответственно при попытке добавить элемент в занятую ячейку &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; начинаем последовательно просматривать ячейки &amp;lt;tex&amp;gt; i+1, i+4, i+9&amp;lt;/tex&amp;gt; и так далее, пока не найдём свободную ячейку.&lt;br /&gt;
&lt;br /&gt;
[[Файл:hashtables3.png|400px|Квадратичный поиск.]]&lt;br /&gt;
&lt;br /&gt;
=== Проверка наличия элемента в таблице===&lt;br /&gt;
&lt;br /&gt;
Проверка осуществляется аналогично добавлению: мы проверяем ячейку &amp;lt;tex&amp;gt;i&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;
Кластеризация замедляет все операции с хеш-таблицей: при добавлении требуется перебирать всё больше элементов, при проверке тоже. Чем больше в таблице элементов, тем больше в ней кластеры и тем выше вероятность того, что добавляемый элемент попадёт в кластер.&lt;br /&gt;
Для защиты от кластеризации используется двойное хеширование и [[Хеширование кукушки|хеширование кукушки]].&lt;br /&gt;
&lt;br /&gt;
=== Удаление элемента без пометок ===&lt;br /&gt;
&lt;br /&gt;
Рассуждение будет описывать случай с линейным поиском хеша. Будем при удалении элемента сдвигать всё последующие на &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; позиций назад. При этом:&lt;br /&gt;
* если в цепочке встречается элемент с другим хешем, то он должен остаться на своём месте (такая ситуация может возникнуть если оставшаяся часть цепочки была добавлена позже этого элемента)&lt;br /&gt;
* в цепочке не должно оставаться &amp;quot;дырок&amp;quot;, тогда любой элемент с данным хешем будет доступен из начала цепи&lt;br /&gt;
&lt;br /&gt;
Учитывая это будем действовать следующим образом: при поиске следующего элемента цепочки будем пропускать все ячейки с другим значением хеша, первый найденный элемент копировать в текущую ячейку, и затем рекурсивно его удалять. Если такой следующей ячейки нет, то текущий элемент можно просто удалить, сторонние цепочки при этом не разрушатся (чего нельзя сказать про случай квадратичного поиска).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
''' Псевдокод '''&lt;br /&gt;
&lt;br /&gt;
 '''function''' delete('''Item''' i):&lt;br /&gt;
      j = i + q&lt;br /&gt;
      '''while''' table[j] == ''null'' '''or''' table[j].key != table[i].key&lt;br /&gt;
         '''if''' table[j] == ''null''&lt;br /&gt;
            table[i] = ''null''&lt;br /&gt;
            '''return'''&lt;br /&gt;
         j += q&lt;br /&gt;
      table[i] = table[j]&lt;br /&gt;
      delete(j)    &lt;br /&gt;
&lt;br /&gt;
Хеш-таблицу считаем зацикленной&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|about=о времени работы&lt;br /&gt;
|statement=Асимптотически время работы &amp;lt;tex&amp;gt;\mathrm{delete}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\mathrm{find}&amp;lt;/tex&amp;gt; совпадают&lt;br /&gt;
|proof=&lt;br /&gt;
Заметим что указатель &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt; в каждой итерации перемещается вперёд на &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; (с учётом рекурсивных вызовов &amp;lt;tex&amp;gt;\mathrm{delete}&amp;lt;/tex&amp;gt;). То есть этот алгоритм последовательно пройдёт по цепочке от удаляемого элемента до последнего {{---}} с учётом вызова &amp;lt;tex&amp;gt;\mathrm{find}&amp;lt;/tex&amp;gt; собственно для нахождения удаляемого элемента, мы посетим все ячейки цепи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Вариант с зацикливанием мы не рассматриваем, поскольку если &amp;lt;tex&amp;gt;q&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;\mathrm{delete}&amp;lt;/tex&amp;gt; (см. псевдокод) заметёт созданную дыру (скопированный элемент), и сам, по предположению, новых не создаст.&lt;br /&gt;
* Элементы, которые уже на своих местах, не должны быть сдвинуты.&lt;br /&gt;
Это учтено.&lt;br /&gt;
* В других цепочках не появятся дыры&lt;br /&gt;
Противное возможно только в том случае, если какой-то элемент был действительно удалён. Удаляем мы только последнюю ячейку в цепи, и если бы на её месте возникла дыра для сторонней цепочки, это бы означало что элемент, стоящий на &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; позиций назад, одновременно принадлежал нашей и другой цепочкам, что невозможно.&lt;br /&gt;
&lt;br /&gt;
==Двойное хеширование==&lt;br /&gt;
'''Двойное хеширование''' (англ. double hashing) {{---}} метод борьбы с коллизиями, возникающими при открытой адресации, основанный на использовании двух хеш-функций для построения различных последовательностей исследования хеш-таблицы.&lt;br /&gt;
&lt;br /&gt;
===Принцип двойного хеширования===&lt;br /&gt;
При двойном хешировании используются две независимые хеш-функции &amp;lt;tex&amp;gt; h_1(k) &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; h_2(k) &amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; {{---}} это наш ключ, &amp;lt;tex&amp;gt; m &amp;lt;/tex&amp;gt; {{---}} размер нашей таблицы, &amp;lt;tex&amp;gt;n \bmod m &amp;lt;/tex&amp;gt; {{---}} остаток от деления &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt; m &amp;lt;/tex&amp;gt;, тогда сначала исследуется ячейка с адресом &amp;lt;tex&amp;gt; h_1(k) &amp;lt;/tex&amp;gt;, если она уже занята, то рассматривается &amp;lt;tex&amp;gt; (h_1(k) +  h_2(k)) \bmod m &amp;lt;/tex&amp;gt;, затем &amp;lt;tex&amp;gt; (h_1(k) +  2 \cdot h_2(k)) \bmod m &amp;lt;/tex&amp;gt; и так далее. В общем случае идёт проверка последовательности ячеек &amp;lt;tex&amp;gt; (h_1(k) +  i \cdot h_2(k)) \bmod m &amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt;  i = (0, 1, \; ... \;,  m - 1) &amp;lt;/tex&amp;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(m)&amp;lt;/tex&amp;gt;, что не отличается от обычного [[Открытое_и_закрытое_хеширование#Линейное разрешение коллизий|линейного разрешения коллизий]].&lt;br /&gt;
Однако в среднем, при грамотном выборе хеш-функций, двойное хеширование будет выдавать лучшие результаты, за счёт того, что вероятность совпадения значений сразу двух независимых хеш-функций ниже, чем одной.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt;\forall x \neq y \; \exists h_1,h_2 : p(h_1(x)=h_1(y))&amp;gt; p((h_1(x)=h_1(y)) \land (h_2(x)=h_2(y)))&amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Выбор хеш-функций===&lt;br /&gt;
&amp;lt;tex&amp;gt; h_1 &amp;lt;/tex&amp;gt; может быть обычной хеш-функцией. Однако чтобы последовательность исследования могла охватить всю таблицу, &amp;lt;tex&amp;gt; h_2 &amp;lt;/tex&amp;gt; должна возвращать значения:&lt;br /&gt;
*не равные &amp;lt;tex&amp;gt; 0 &amp;lt;/tex&amp;gt;&lt;br /&gt;
*независимые  от &amp;lt;tex&amp;gt; h_1 &amp;lt;/tex&amp;gt;&lt;br /&gt;
*взаимно простые с величиной хеш-таблицы&lt;br /&gt;
&lt;br /&gt;
Есть два удобных способа это сделать. Первый состоит в том, что в качестве размера таблицы используется простое число, а &amp;lt;tex&amp;gt; h_2 &amp;lt;/tex&amp;gt; возвращает натуральные числа, меньшие &amp;lt;tex&amp;gt; m &amp;lt;/tex&amp;gt;. Второй {{---}} размер таблицы является степенью двойки, а &amp;lt;tex&amp;gt; h_2 &amp;lt;/tex&amp;gt; возвращает нечетные значения.&lt;br /&gt;
&lt;br /&gt;
Например, если размер таблицы равен &amp;lt;tex&amp;gt; m &amp;lt;/tex&amp;gt;, то в качестве &amp;lt;tex&amp;gt; h_2 &amp;lt;/tex&amp;gt; можно использовать функцию вида &amp;lt;tex&amp;gt; h_2(k) = k \bmod (m-1) + 1 &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Файл: Вставка при двойном хэшировании.svg.jpeg|thumb|right|Вставка при двойном хешировании]]&lt;br /&gt;
&lt;br /&gt;
===Пример===&lt;br /&gt;
&lt;br /&gt;
Показана хеш-таблица размером 13 ячеек, в которой используются вспомогательные функции:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt; h(k,i) = (h_1(k) + i \cdot h_2(k)) \bmod 13 &amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt; h_1(k) = k \bmod 13 &amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt; h_2(k) = 1 + k \bmod 11 &amp;lt;/tex&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Мы хотим вставить ключ 14. Изначально &amp;lt;tex&amp;gt; i = 0 &amp;lt;/tex&amp;gt;. Тогда &amp;lt;tex&amp;gt; h(14,0) = (h_1(14) + 0\cdot h_2(14)) \bmod 13 = 1 &amp;lt;/tex&amp;gt;. Но ячейка с индексом 1 занята, поэтому увеличиваем &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; на 1 и пересчитываем значение хеш-функции. Делаем так, пока не дойдем до пустой ячейки. При &amp;lt;tex&amp;gt; i = 2 &amp;lt;/tex&amp;gt; получаем &amp;lt;tex&amp;gt; h(14,2) = (h_1(14) + 2\cdot h_2(14)) \bmod 13 = 9 &amp;lt;/tex&amp;gt;. Ячейка с номером 9 свободна, значит записываем туда наш ключ.&lt;br /&gt;
&lt;br /&gt;
Таким образом, основная особенность двойного хеширования состоит в том, что при различных &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; пара &amp;lt;tex&amp;gt; (h_1(k),h_2(k)) &amp;lt;/tex&amp;gt; дает различные последовательности ячеек для исследования.&lt;br /&gt;
&lt;br /&gt;
===Простая реализация===&lt;br /&gt;
Пусть у нас есть некоторый объект &amp;lt;tex&amp;gt; item &amp;lt;/tex&amp;gt;, в котором определено поле &amp;lt;tex&amp;gt; key &amp;lt;/tex&amp;gt;, от которого можно вычислить хеш-функции &amp;lt;tex&amp;gt; h_1(key)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; h_2(key) &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Так же у нас есть таблица &amp;lt;tex&amp;gt; table &amp;lt;/tex&amp;gt; величиной &amp;lt;tex&amp;gt; m &amp;lt;/tex&amp;gt;, состоящая из объектов типа &amp;lt;tex&amp;gt; item &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Вставка'''&lt;br /&gt;
 '''function''' add('''Item''' item):&lt;br /&gt;
      x = h1(item.key)&lt;br /&gt;
      y = h2(item.key)&lt;br /&gt;
      '''for''' (i = 0..m)    	&lt;br /&gt;
         '''if''' table[x] == ''null''&lt;br /&gt;
            table[x] = item&lt;br /&gt;
            '''return'''      &lt;br /&gt;
         x = (x + y) '''mod''' m   &lt;br /&gt;
      table.resize()&amp;lt;span style=&amp;quot;color:Green&amp;quot;&amp;gt;// ошибка, требуется увеличить размер таблицы&lt;br /&gt;
&lt;br /&gt;
'''Поиск'''&lt;br /&gt;
 '''Item''' search('''Item''' key):&lt;br /&gt;
      x = h1(key)&lt;br /&gt;
      y = h2(key)&lt;br /&gt;
      '''for''' (i = 0..m)&lt;br /&gt;
         '''if''' table[x] != ''null''&lt;br /&gt;
            '''if''' table[x].key == key&lt;br /&gt;
               '''return''' table[x]&lt;br /&gt;
         '''else'''&lt;br /&gt;
            '''return''' ''null''&lt;br /&gt;
         x = (x + y) '''mod''' m   &lt;br /&gt;
      '''return''' ''null''&lt;br /&gt;
&lt;br /&gt;
===Реализация с удалением===&lt;br /&gt;
Чтобы наша хеш-таблица поддерживала удаление, требуется добавить массив &amp;lt;tex&amp;gt;deleted&amp;lt;/tex&amp;gt; типов &amp;lt;tex&amp;gt;bool&amp;lt;/tex&amp;gt;, равный по величине массиву &amp;lt;tex&amp;gt;table&amp;lt;/tex&amp;gt;. Теперь при удалении мы просто будем помечать наш объект ''как удалённый'', а при добавлении как ''не удалённый'' и замещать новым добавляемым объектом. При поиске, помимо равенства ключей, мы смотрим, удалён ли элемент, если да, то идём дальше.&lt;br /&gt;
&lt;br /&gt;
'''Вставка'''&lt;br /&gt;
 '''function''' add('''Item''' item):&lt;br /&gt;
      x = h1(item.key)&lt;br /&gt;
      y = h2(item.key)&lt;br /&gt;
      '''for''' (i = 0..m)   	&lt;br /&gt;
         '''if''' table[x] == '''null''' '''or''' deleted[x]&lt;br /&gt;
            table[x] = item&lt;br /&gt;
            deleted[x] = '''false'''&lt;br /&gt;
            '''return'''      &lt;br /&gt;
         x = (x + y) '''mod''' m   &lt;br /&gt;
      table.resize()&amp;lt;span style=&amp;quot;color:Green&amp;quot;&amp;gt;// ошибка, требуется увеличить размер таблицы&lt;br /&gt;
'''Поиск'''&lt;br /&gt;
 '''Item''' search('''Item''' key):&lt;br /&gt;
      x = h1(key)&lt;br /&gt;
      y = h2(key)&lt;br /&gt;
      '''for''' (i = 0..m) &lt;br /&gt;
         '''if''' table[x] != '''null'''&lt;br /&gt;
            '''if''' table[x].key == key '''and''' !deleted[x]&lt;br /&gt;
               '''return''' table[x]&lt;br /&gt;
         '''else'''&lt;br /&gt;
            '''return''' '''null'''&lt;br /&gt;
         x = (x + y) '''mod''' m   &lt;br /&gt;
      '''return''' '''null'''&lt;br /&gt;
&lt;br /&gt;
'''Удаление'''&lt;br /&gt;
 '''function''' remove('''Item''' key):&lt;br /&gt;
      x = h1(key)&lt;br /&gt;
      y = h2(key)&lt;br /&gt;
      '''for''' (i = 0..m)&lt;br /&gt;
         '''if''' table[x] != '''null'''&lt;br /&gt;
            '''if''' table[x].key == key&lt;br /&gt;
               deleted[x] = '''true'''&lt;br /&gt;
         '''else''' &lt;br /&gt;
            '''return'''&lt;br /&gt;
         x = (x + y) '''mod''' m&lt;br /&gt;
&lt;br /&gt;
==Альтернативная реализация метода цепочек==&lt;br /&gt;
В Java 8 для разрешения коллизий используется модифицированный метод цепочек. Суть его заключается в том, что когда количество элементов в корзине превышает определенное значение, данная корзина переходит от использования связного списка к использованию [[АВЛ-дерево|сбалансированного дерева]]. Но данный метод имеет смысл лишь тогда, когда на элементах хеш-таблицы задан [[Отношение порядка|линейный порядок]]. То есть при использовании данный типа &amp;lt;tex&amp;gt;\mathbf{int}&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;\mathbf{double}&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;. Данный способ используется в таких коллекциях как HashMap, LinkedHashMap и ConcurrentHashMap.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Hashing_in_Java8.png|500px|Хеширование в Java 8.]]&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Хеширование]]&lt;br /&gt;
* [[Хеширование_кукушки|Хеширование кукушки]]&lt;br /&gt;
* [[Идеальное_хеширование|Идеальное хеширование]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Бакнелл Дж. М. «Фундаментальные алгоритмы и структуры данных в Delphi», 2003&lt;br /&gt;
* Кормен, Томас Х., Лейзерсон, Чарльз И., Ривест, Рональд Л., Штайн Клиффорд «Алгоритмы: построение и анализ», 2-е издание. Пер. с англ. — М.:Издательский дом &amp;quot;Вильямс&amp;quot;, 2010.— Парал. тит. англ. — ISBN 978-5-8459-0857-5 (рус.)&lt;br /&gt;
* Дональд Кнут. «Искусство программирования, том 3. Сортировка и поиск» {{---}} «Вильямс», 2007 г.{{---}} ISBN 0-201-89685-0&lt;br /&gt;
* Седжвик Р. «Фундаментальные алгоритмы на C. Части 1-4. Анализ. Структуры данных. Сортировка. Поиск», 2003&lt;br /&gt;
* [http://openjdk.java.net/jeps/180 Handle Frequent HashMap Collisions with Balanced Trees]&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Double_hashing Wikipedia {{---}} Double_hashing]&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/%D0%A5%D0%B5%D1%88-%D1%82%D0%B0%D0%B1%D0%BB%D0%B8%D1%86%D0%B0 Разрешение коллизий]&lt;br /&gt;
* [http://rain.ifmo.ru/cat/view.php/vis/hashtables/hash-2001-2 Пример хеш таблицы]&lt;br /&gt;
* [http://research.cs.vt.edu/AVresearch/hashing/double.php Пример хеш таблицы с двойным хешированием]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Хеширование]]&lt;br /&gt;
[[Категория: Структуры данных]]&lt;/div&gt;</summary>
		<author><name>37.214.24.12</name></author>	</entry>

	</feed>