Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
VB-2012 / 2-cеместр / Дневники / Самостоятельная работа / Лекция 2_9. Хеширование.doc
Скачиваний:
19
Добавлен:
26.03.2015
Размер:
2.41 Mб
Скачать
      1. Удаление элементов

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

Предположим, что элемент Aнаходится в тестовой последовательности элементаB. Если удалить из таблицы элементA, найти элементBбудет невозможно. Во время поиска элементаBвстретится пустая ячейка, которая осталась после удаления элементаA, поэтому будет сделан неправильный вывод о том, что элементBотсутствует в таблице.

Вместо удаления элемента из хеш‑таблицы можно просто пометить его как удаленный. Можно использовать эту ячейку позднее, если она встретится во время выполнения вставки нового элемента в таблицу. Если помеченный элемент встречается во время поиска другого элемента, он просто игнорируется и тестовая последовательность продолжится.

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

        1. Рехеширование

Чтобы освободить удаленные элементы из хеш‑таблицы, можно выполнить ее рехеширование (rehashing) на месте. Чтобы этот алгоритм мог работать, нужно иметь какой‑то способ для определения, было ли выполнено рехеширование элемента. Простейший способ сделать это — определить элементы в виде структур данных, содержащих полеRehashed.

Type ItemType

Value As Long

Rehashed As Boolean

End Type

Вначале присвоим полю Rehashedзначениеfalse. Затем выполним проход по таблице в поиске ячеек, которые не помечены как удаленные, и для которых еще не было выполнено рехеширование.

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

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

        1. Изменение размера хеш‑таблиц

Если хеш‑таблица становится почти заполненной, производительность значительно падает. В этом случае может понадобиться увеличение размера таблицы, чтобы в ней было больше места для элементов. И наоборот, если в таблице слишком мало ячеек, может потребоваться уменьшить ее, чтобы освободить занимаемую память. Используя методы, похожие на те, которые использовались при рехешировании таблицы на месте, можно увеличивать и уменьшать размер хеш‑таблицы.

Чтобы увеличить хеш‑таблицу, вначале размер массива, в котором она находится, увеличивается при помощи оператора Dim Preserve. Затем выполняется рехеширование таблицы, при этом элементы могут занимать ячейки в созданной свободной области в конце таблицы. После завершения рехеширования таблица будет готова к использованию.

Чтобы уменьшить размер таблицы, вначале определим, сколько элементов должно содержаться в массиве таблицы после уменьшения. Затем выполняем рехеширование таблицы, причем элементы помещаются только в уменьшенную часть таблицы. После завершения рехеширования всех элементов, размер массива уменьшается при помощи оператора ReDim Preserve.

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

Public Sub Rehash()

Dim i As Integer

Dim pos As Integer

Dim probes As Integer

Dim Value As Long

Dim new_value As Long

' Пометить все элементы как нерехешированные.

For i = 0 To NumEntries - 1

m_HashTable(i).Rehashed = False

Next i

' Поиск нерехешированных элементов.

For i = 0 To NumEntries - 1

If Not m_HashTable(i).Rehashed Then

Value = m_HashTable(i).Value

m_HashTable(i).Value = UNUSED

If Value <> DELETED And Value <> UNUSED Then

' Выполнить тестовую последовательность

' для этого элемента, пока не найдется свободная,

' удаленная или нерехешированная ячейка.

probes = 0

Do

pos = (Value + probes) Mod NumEntries

new_value = m_HashTable(pos).Value

' Если ячейка свободна или помечена как

' удаленная, поместить элемент в нее.

If new_value = UNUSED Or _

new_value = DELETED _

Then

m_HashTable(pos).Value = Value

m_HashTable(pos).Rehashed = True

Exit Do

End If

' Если ячейка не помечена как рехешированная,

' поменять их местами и продолжить.

If Not m_HashTable(pos).Rehashed Then

m_HashTable(pos).Value = Value

m_HashTable(pos).Rehashed = True

Value = new_value

probes = 0

Else

probes = probes + 1

End If

Loop

End If

End If

Next i

End Sub

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

19