Расширяемое хеширование — различия между версиями

Материал из Викиконспекты
Перейти к: навигация, поиск
Строка 1: Строка 1:
 
'''Метод расширяемого хеширования''' (англ. ''extendable hashing'') заключается в том, что мы представляем хеш-таблицу в качестве нескольких групп, которые имеют определенное количество ячеек. При переполнении группы нам не требуется перехешировать всю таблицу, а лишь перехешировать заполненную группу, разделив ее при этом на две группы. Таким образом вся хеш-таблица никогда не будет полностью заполнена. К тому же при использовании данного метода использование памяти будет наиболее экономичным.
 
'''Метод расширяемого хеширования''' (англ. ''extendable hashing'') заключается в том, что мы представляем хеш-таблицу в качестве нескольких групп, которые имеют определенное количество ячеек. При переполнении группы нам не требуется перехешировать всю таблицу, а лишь перехешировать заполненную группу, разделив ее при этом на две группы. Таким образом вся хеш-таблица никогда не будет полностью заполнена. К тому же при использовании данного метода использование памяти будет наиболее экономичным.
 
== Алгоритм ==
 
== Алгоритм ==
Посмотрим, как работает алгоритм, на примере заполнения гипотетической хеш-таблицы. Первоначально в таблице имеется одна группа. Предположим, что каждая группа будет содержать 10 хеш-значений и номер записи каждого хеш-значения, чтобы ее можно было извлечь.
+
В начале у нас есть хеш-таблица с первоначальным количеством ячеек. Все эти ячейки будут являться первой группой.Предположим, что каждая группа будет содержать <tex> 10 </tex> значений и номер записи каждого значения, чтобы ее можно было извлечь.
  
Начнем вставлять в таблицу хеш-значения вместе с номерами их записей. При наличии только одной группы их можно вставить только в одно место, поэтому после 10 вставок группа заполняется. Разобьем заполненную группу на две группы одинаковых размеров и повторим вставку всех элементов исходной группы в две новые группы. Причем все элементы, которые завершаются нулевым разрядом, поместим в одну группу, а завершающиеся единичным разрядом — в другую. Эти две группы имеют так называемую '''разрядную глубину''' (англ. ''bit—depth''), равную одному разряду. Теперь при каждой вставке пары хеш-значение/номер записи она будет помещаться в первую или во вторую группу, в зависимости от последнего разряда хеш-значения.
+
Начнем вставлять в таблицу значения вместе с номерами их записей. При наличии только одной группы их можно вставить только в одно место, поэтому после 10 вставок группа заполняется. Разобьем заполненную группу на две группы одинаковых размеров и повторим вставку всех элементов исходной группы в две новые группы. Причем все элементы, которые завершаются нулевым разрядом, поместим в одну группу, а завершающиеся единичным разрядом — в другую. Эти две группы имеют так называемую '''разрядную глубину''' (англ. ''bit—depth''), равную одному разряду. Теперь при каждой вставке пары значение/номер записи она будет помещаться в первую или во вторую группу, в зависимости от последнего разряда значения.
  
Со временем мы заполним еще одну группу. Предположим, что это группа, в которую мы вставляли все хеш-значения, завершающиеся 0. Снова разобьем группу на две отдельные группы. На этот раз все элементы, хеш-значения которых заканчиваются двумя нулевыми разрядами, т.е. 00, будут помещаться в первую группу, а завершающиеся разрядами 10 — во вторую группу. Обе группы имеют разрядную глубину, равную 2. Поэтому для определения места вставки необходимо проверять два младших разряда хеш-значения. Теперь у нас имеются три группы: в первую вставляются элементы, завершающиеся разрядами 00, во вторую — разрядами 10, а в третью — просто 1.
+
Со временем мы заполним еще одну группу. Предположим, что это группа, в которую мы вставляли все значения, завершающиеся 0. Снова разобьем группу на две отдельные группы. На этот раз все элементы, значения которых заканчиваются двумя нулевыми разрядами, т.е. <tex>00</tex>, будут помещаться в первую группу, а завершающиеся разрядами <tex>10</tex> — во вторую группу. Обе группы имеют разрядную глубину, равную 2. Поэтому для определения места вставки необходимо проверять два младших разряда значения. Теперь у нас имеются три группы: в первую вставляются элементы, завершающиеся разрядами <tex>00</tex>, во вторую — разрядами <tex>10</tex>, а в третью — просто <tex>1</tex>. И так далее.
  
Предположим, что мы продолжаем вставку и заполняем группу 10. Мы снова разбиваем заполненную группу на две и повторяем вставку ее элементов в две новые группы. На этот раз две новые группы будут принимать элементы, завершающиеся разрядами 010 и 110. Таким образом, теперь у нас имеются четыре группы: одна с разрядной глубиной, равной 1, в которую выполняется вставка хеш-значений, завершающихся 1, одна с разрядной глубиной равной 2, содержащая хеш-значения, которые завершаются разрядами 00, и две группы с разрядной глубиной, равной 3, которые предназначены для хеш-значений, завершающихся разрядами 010 и 110.
+
Для поддержания отображения того, какие значения помещаются в те или иные группы, используется структура, называемая каталогом (англ. ''catalogue''). По существу каталог содержит список всех возможных окончаний групп и связных с ними номеров групп. Вместо того чтобы поддерживать какой—либо причудливый набор значений разрядной глубины и номеров групп, выбранный методом проб и ошибок, каталог поддерживает собственное значение разрядной глубины, равное максимальной разрядной глубине группы, и имеет ячейку для каждого значения этой разрядной глубины.
 
 
Для поддержания отображения того, какие хеш-значения помещаются в те или иные группы, используется структура, называемая каталогом (англ. ''catalogue''). По существу каталог содержит список всех возможных окончаний групп и связных с ними номеров групп. Вместо того чтобы поддерживать какой—либо причудливый набор значений разрядной глубины и номеров групп, выбранный методом проб и ошибок, каталог поддерживает собственное значение разрядной глубины, равное максимальной разрядной глубине группы, и имеет ячейку для каждого значения этой разрядной глубины.
 
 
 
В рассмотренном нами примере максимальная разрядная глубина группы была равна 3, поэтому разрядная глубина каталога также равна этому значению. Три разряда позволяют образовать восемь комбинаций разрядов: 000, 001, 010, 011, 100, 101, 110 и 111. Все комбинации, которые завершаются 1 (т.е. вторая, четвертая, шестая и восьмая), указывают на одну и ту же группу, принимающую элементы, хеш-значения которых завершаются 1. Аналогично, записи каталога для значений 000 и 100 указывают на одну и ту же группу, в которую помещаются элементы с хеш-значениями, завершающимися разрядами 00.
 
  
 
[[Файл:7_1.png|400px|мини|Вставка в расширяемую хеш-таблицу]]
 
[[Файл:7_1.png|400px|мини|Вставка в расширяемую хеш-таблицу]]
  
===Примечание===
+
При разбиении группы дополняющие друг друга группы не будут размещаться в каталоге по соседству. Для дальнейших рассуждений было бы проще предположить, что записи каталога, соответствующие одной группе, располагаются по соседству, чтобы при разбиении группы дополняющая первую группа помещалась непосредственно за ней.
 
 
Однако эта схема не учитывает ряд особенностей. Две записи каталога, которые указывают на группу для элементов, хеш-значения которых завершаются разрядами 00, разделены тремя другими записями. Аналогично единственной группе, принимающей все элементы, хеш-значения которых завершаются 1, соответствуют четыре записи, равномерно распределенные по каталогу. При разбиении группы дополняющие друг друга группы не будут размещаться в каталоге по соседству. Для дальнейших рассуждений было бы проще предположить, что записи каталога, соответствующие одной группе, располагаются по соседству, чтобы при разбиении группы дополняющая первую группа помещалась непосредственно за ней.
 
  
Для достижения этого следует инвертировать последние разряды хеш-значения при вычислении индексной записи каталога. Так, например, если хеш-значение завершается разрядами 001, при поиске мы обратимся не к записи 001 каталога, а к записи 100 (4, которая соответствует инвертированному значению 001). В результате использование каталога значительно упрощается. В нашем примере хеш-значения, которые завершаются разрядами 00, помещаются в запись каталога 000 (0) или 001 (1). Хеш-значения, которые завершаются разрядами 010, помещаются в запись каталога 010 (2). Хеш-значения, которые завершаются разрядами 011, помещаются в запись каталога 011 (3). И, наконец, хеш-значения, которые завершаются разрядом 1, помещаются в записи 100, 101, 110 или 111 (4, 5, 6, 7).
+
Для достижения этого следует инвертировать последние разряды хеш-значения при вычислении индексной записи каталога. Так, например, если хеш-значение завершается разрядами <tex>001</tex>, при поиске мы обратимся не к записи <tex>001</tex> каталога, а к записи <tex>100</tex> (<tex>4</tex>, которая соответствует инвертированному значению <tex>001</tex>). В результате использование каталога значительно упрощается.
  
===Визуализация===
+
==Пример==
  
Вернемся немного назад, и вставим элементы в пустую хеш-таблицу, как это было сделано ранее. Выполняемые при этом действия показаны на рис. Мы начинаем с каталога только с одной записью с индексом 0 (a). Принято считать, что в подобной ситуации разрядная глубина равна 0. Мы заполняем единственную группу (назовем ее  <tex> A </tex> ) и теперь ее нужно разбить. Вначале мы увеличиваем разрядную глубину каталога до 1. Иначе говоря, теперь он будет содержать две записи (b). В результате будут созданы две группы, на первую из которых указывает запись 0 (исходная запись  <tex> A </tex> ), а на вторую — запись 1,  <tex> B </tex>  (c). Все элементы, хеш-значения которых завершаются разрядом 0, помещаются в группу  <tex> A </tex> , а остальные — в группу  <tex> B </tex> . Снова заполним группу  <tex> A </tex> . Теперь разрядную глубину каталога необходимо увеличить с 1 до 2, чтобы получить четыре группы, доступных для вставки. Перед разделением заполненной группы записи каталога 00 и 01 будут указывать на исходную группу  <tex> A </tex> , а записи 10 и 11 — на группу  <tex> B </tex>  (d). Группа  <tex> A </tex>  разбивается на группу, которая принимает хеш-значения с окончанием 00 (снова  <tex> A </tex> ), и группу, которая принимает хеш-значения с окончанием 10,  <tex> C </tex> . На группу  <tex> A </tex>  будет указывать запись 00 каталога, а на группу  <tex> C </tex>  — запись 01 (e). И, наконец, группа  <tex> C </tex>  (на которую указывает запись 01 каталога) заполняется. Нужно снова увеличить разрядную глубину каталога, на этот раз до трех разрядов.
+
Рассмотрим выполнение алгоритма на примере, выполняемые при этом действия показаны на рис. Мы начинаем с каталога только с одной записью с индексом <tex>0</tex> (a). Принято считать, что в подобной ситуации разрядная глубина равна <tex>0</tex>. Мы заполняем единственную группу (назовем ее  <tex> A </tex> ) и теперь ее нужно разбить. Вначале мы увеличиваем разрядную глубину каталога до <tex>1</tex>. Иначе говоря, теперь он будет содержать две записи (b). В результате будут созданы две группы, на первую из которых указывает запись <tex>0</tex> (исходная запись  <tex> A </tex> ), а на вторую — запись <tex>1</tex>,  <tex> B </tex>  (c). Все элементы, значения которых завершаются разрядом <tex>0</tex>, помещаются в группу  <tex> A </tex> , а остальные — в группу  <tex> B </tex> . Снова заполним группу  <tex> A </tex> . Теперь разрядную глубину каталога необходимо увеличить с <tex>1</tex> до <tex>2</tex>, чтобы получить четыре группы, доступных для вставки. Перед разделением заполненной группы записи каталога <tex>00</tex> и <tex>01</tex> будут указывать на исходную группу  <tex> A </tex> , а записи <tex>10</tex> и <tex>11</tex> — на группу  <tex> B </tex>  (d). Группа  <tex> A </tex>  разбивается на группу, которая принимает значения с окончанием <tex>00</tex> (снова  <tex> A </tex> ), и группу, которая принимает значения с окончанием <tex>10</tex>,  <tex> C </tex> . На группу  <tex> A </tex>  будет указывать запись <tex>00</tex> каталога, а на группу  <tex> C </tex>  — запись <tex>01</tex> (e). И, наконец, группа  <tex> C </tex>  (на которую указывает запись 01 каталога) заполняется. Нужно снова увеличить разрядную глубину каталога, на этот раз до трех разрядов.
 +
== Использование ==
 +
Чаще всего расширяемое хеширование используется в базах данных т.к. БД могут быть крайне большими и перехеширование всей БД займет продолжительное время при этом лишая пользователей доступа к БД. А при использовании расширяемого хеширования перехешировать придется только малые группы, что не сильно замедлит работу БД.
 
== См. также ==
 
== См. также ==
 
*[[Хеш-таблица]]
 
*[[Хеш-таблица]]

Версия 16:14, 6 июня 2015

Метод расширяемого хеширования (англ. extendable hashing) заключается в том, что мы представляем хеш-таблицу в качестве нескольких групп, которые имеют определенное количество ячеек. При переполнении группы нам не требуется перехешировать всю таблицу, а лишь перехешировать заполненную группу, разделив ее при этом на две группы. Таким образом вся хеш-таблица никогда не будет полностью заполнена. К тому же при использовании данного метода использование памяти будет наиболее экономичным.

Алгоритм

В начале у нас есть хеш-таблица с первоначальным количеством ячеек. Все эти ячейки будут являться первой группой.Предположим, что каждая группа будет содержать [math] 10 [/math] значений и номер записи каждого значения, чтобы ее можно было извлечь.

Начнем вставлять в таблицу значения вместе с номерами их записей. При наличии только одной группы их можно вставить только в одно место, поэтому после 10 вставок группа заполняется. Разобьем заполненную группу на две группы одинаковых размеров и повторим вставку всех элементов исходной группы в две новые группы. Причем все элементы, которые завершаются нулевым разрядом, поместим в одну группу, а завершающиеся единичным разрядом — в другую. Эти две группы имеют так называемую разрядную глубину (англ. bit—depth), равную одному разряду. Теперь при каждой вставке пары значение/номер записи она будет помещаться в первую или во вторую группу, в зависимости от последнего разряда значения.

Со временем мы заполним еще одну группу. Предположим, что это группа, в которую мы вставляли все значения, завершающиеся 0. Снова разобьем группу на две отдельные группы. На этот раз все элементы, значения которых заканчиваются двумя нулевыми разрядами, т.е. [math]00[/math], будут помещаться в первую группу, а завершающиеся разрядами [math]10[/math] — во вторую группу. Обе группы имеют разрядную глубину, равную 2. Поэтому для определения места вставки необходимо проверять два младших разряда значения. Теперь у нас имеются три группы: в первую вставляются элементы, завершающиеся разрядами [math]00[/math], во вторую — разрядами [math]10[/math], а в третью — просто [math]1[/math]. И так далее.

Для поддержания отображения того, какие значения помещаются в те или иные группы, используется структура, называемая каталогом (англ. catalogue). По существу каталог содержит список всех возможных окончаний групп и связных с ними номеров групп. Вместо того чтобы поддерживать какой—либо причудливый набор значений разрядной глубины и номеров групп, выбранный методом проб и ошибок, каталог поддерживает собственное значение разрядной глубины, равное максимальной разрядной глубине группы, и имеет ячейку для каждого значения этой разрядной глубины.

Вставка в расширяемую хеш-таблицу

При разбиении группы дополняющие друг друга группы не будут размещаться в каталоге по соседству. Для дальнейших рассуждений было бы проще предположить, что записи каталога, соответствующие одной группе, располагаются по соседству, чтобы при разбиении группы дополняющая первую группа помещалась непосредственно за ней.

Для достижения этого следует инвертировать последние разряды хеш-значения при вычислении индексной записи каталога. Так, например, если хеш-значение завершается разрядами [math]001[/math], при поиске мы обратимся не к записи [math]001[/math] каталога, а к записи [math]100[/math] ([math]4[/math], которая соответствует инвертированному значению [math]001[/math]). В результате использование каталога значительно упрощается.

Пример

Рассмотрим выполнение алгоритма на примере, выполняемые при этом действия показаны на рис. Мы начинаем с каталога только с одной записью с индексом [math]0[/math] (a). Принято считать, что в подобной ситуации разрядная глубина равна [math]0[/math]. Мы заполняем единственную группу (назовем ее [math] A [/math] ) и теперь ее нужно разбить. Вначале мы увеличиваем разрядную глубину каталога до [math]1[/math]. Иначе говоря, теперь он будет содержать две записи (b). В результате будут созданы две группы, на первую из которых указывает запись [math]0[/math] (исходная запись [math] A [/math] ), а на вторую — запись [math]1[/math], [math] B [/math] (c). Все элементы, значения которых завершаются разрядом [math]0[/math], помещаются в группу [math] A [/math] , а остальные — в группу [math] B [/math] . Снова заполним группу [math] A [/math] . Теперь разрядную глубину каталога необходимо увеличить с [math]1[/math] до [math]2[/math], чтобы получить четыре группы, доступных для вставки. Перед разделением заполненной группы записи каталога [math]00[/math] и [math]01[/math] будут указывать на исходную группу [math] A [/math] , а записи [math]10[/math] и [math]11[/math] — на группу [math] B [/math] (d). Группа [math] A [/math] разбивается на группу, которая принимает значения с окончанием [math]00[/math] (снова [math] A [/math] ), и группу, которая принимает значения с окончанием [math]10[/math], [math] C [/math] . На группу [math] A [/math] будет указывать запись [math]00[/math] каталога, а на группу [math] C [/math] — запись [math]01[/math] (e). И, наконец, группа [math] C [/math] (на которую указывает запись 01 каталога) заполняется. Нужно снова увеличить разрядную глубину каталога, на этот раз до трех разрядов.

Использование

Чаще всего расширяемое хеширование используется в базах данных т.к. БД могут быть крайне большими и перехеширование всей БД займет продолжительное время при этом лишая пользователей доступа к БД. А при использовании расширяемого хеширования перехешировать придется только малые группы, что не сильно замедлит работу БД.

См. также

Источники информации

  • Бакнелл Джулиан — Фундаментальные алгоритмы и структуры данных в Delphi — стр. 50.
  • Дейт К. Дж. — Введение в системы баз данных, 8-е издание.: Пер. с англ. — М.: Издательский дом «Вильямс», 2005. — стр. 1236.