Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
17
Добавлен:
16.05.2015
Размер:
867.84 Кб
Скачать

2.3.3. М-блочный поиск

Этот способ удобен при индексном хранении списка. Предполагается, что исходный упорядоченный список B длины N разбит на M подсписков B1,B2,...,Bm длины N1,N2,...,Nm, таким образом, что B=b1,b2,..,bm.

Для нахождения ключа V, нужно сначала определить первый из списков Bi, i=1,m, последний элемент которого больше v, а потом применить последовательный поиск к списку bi.

Хранение списков Bi может быть связным или последовательным. Если длины всех подсписков приблизительно равны и M= n, то max М-блочного поиска равен 2 n. При одинаковой частоте использования элементов avg М-блочного поиска равен n.

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

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

2.3.4. Методы вычисления адреса

Методы вычисления адреса. Пусть в каждом из М элементов массива Т содержится элемент списка (например целое положительное число). Если имеется некоторая функция H(V), вычисляющая однозначно по элементу V его адрес - целое положительное число из интервала [0,M-1],то V можно хранить в массиве T с номером H(V) т.е. V=t(h(v)). При таком хранении поиск любого элемента происходит за постоянное время не зависящее от m.

Массив T называется массивом хеширования, а функция H - функцией хеширования.

При конкретном применении хеширования обычно имеется определенная область возможных значений элементов списка V и некоторая информация о них. На основе этого выбирается размер массива хеширования M и строится функция хеширования. Критерием для выбора M и H является возможность их эффективного использования.

Пусть нужно хранить линейный список из элементов K1,K2,..,Kn, таких, что при Ki=kj, mod(ki,26)= mod(kj,26). Для хранения списка выберем массив хеширования t(26) с пространством адресов 0-25 и функцию хеширования h(v)= mod(v,26). Массив t заполняется элементами t(h(ki))=ki и t(j)=0 если j (h(k1), h(k2),..,h(kn)).

Поиск элемента V в массиве T с присваиванием Z его индекса если V содержится в T, или -1, если V не содержится в T, осуществляется следующим образом

int t[26],v,z,i;

i=(int)fmod((double)v,26.0);

if(t[i]==v) z=i;

else z=-1;

Добавление нового элемента V в список с возвращением в Z индекса элемента, где он будет храниться, реализуется фрагментом

z=(int)fmod((doule)v,26.0);

t[z]=v;

а исключение элемента V из списка присваиванием

t[(int)fmod((double)v,26)]=0;

Теперь рассмотрим более сложный случай, когда условие Ki=kj h(ki)=h(kj) не выполняется. Пусть v - множество возможных элементов списка (целые положительные числа), в котором максимальное число элементов равно 6. Возьмем m=8 и в качестве функции хеширования выберем функцию h(v)=mod(v,8).

Предположим, что B=, причем H(K1)=5, h(k2)=3, h(k3)=6, h(k4)=3, h(k5)=1, т.е. h(k2)=h(k4) хотя k2=k4. Такая ситуация называется коллизией, и в этом случае при заполнении массива хеширования требуется метод для ее разрешения. Обычно выбирается первая свободная ячейка за собственным адресом. Для нашего случая массив t[8] может иметь вид

T=<0,K5,0,K2,K4,K1,K3,0> .

При наличии коллизий усложняются все алгоритмы работы с массивом хеширования. Рассмотрим работу с массивом T[100], т.е. с пространством адресов от 0 до 99. Пусть количество элементов N не более 99, тогда в T всегда будет хотя бы один свободный элемент равный нулю. Для объявления массива используем оператор

int static t[100];

Добавление в массив T нового элемента Z с занесением его адреса в I и числа элементов в N выполняется так:

i=h(z);

while (t[i]!=0 && t[i]!=z)

if (i==99) i=0;

else i++;

if (t[i]!=z) t[i]=z, n++;

Поиск в массиве T элемента Z с присвоением I индекса Z, если Z имеется в T, или I=-1, если такого элемента нет, реализуется следующим образом:

i=h(z);

while (t[i]!=0 && t[i]!=z)

if (i==99) i=0;

else i++;

if (t[i]==0) i=-1;

При наличии коллизий исключение элемента из списка путем пометки его как пустого, т.е. t[i]=0, может привести к ошибке. Например, если из списка b исключить элемент k2, то получим массив хеширования в виде t=<0,K5,0,0,K4,K1,K3,0>, в котором невозможно найти элемент K4, поскольку H(K4)=3, а t(3)=0. В таких случаях при исключении элемента из списка можно записывать в массив хеширования некоторое значение непринадлежащее области значений элементов списка и не равное нулю. При работе с таким массивом это значение будет указывать на то, что нужно просматривать со средние ячейки.

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

Соседние файлы в папке AdditionalLiterature
  • #
    16.05.2015867.84 Кб17Language_C.doc
  • #
    16.05.201520.75 Mб12Uotson, Neygel Visual C# 2008 Base course.djvu