|
Новости |
ХЕШИРОВАНИЕХешированием называется процесс выделения элемента индексно- го массива непосредственно по информации, которая содержится в массиве. Полученный индекс называется хеш-адресом. Хеширование обычно используется для уменьшения времени доступа к дисковым файлам. Однако, тот же метод можно использовать для реализации разреженных матриц. В приводимом ниже примере используется проце- дура, где применяется специальная форма хеширования, называемая прямым индексированием. При прямом индексировании каждому ключу соответствует одна и только одна ячейка. (Т.е. хеширование дает уникальный индекс для каждого ключа. Однако, следует заметить, что применение массива указателей не обязательно требует исполь- зования прямой индексации; просто для решения данной задачи такой подход является очевидным). На практике такая схема прямого хеши- рования используется не очень часто и чаще требуется более гибкий метод. В этом разделе будут рассмотрены более общие методы хеши- рования, более мощные и более гибкие. Из предыдущего примера по электронной матрице ясно, что даже в особых случаях не все ячейки будут использованы. Предположим, что в большинстве случаев не более десяти процентов потенциальных ячеек будет действительно использовано. Это значит, что логичес- кий массив с размерами 26х100 (2600 ячеек) потребует в действи- тельности иметь память только под 260 элементов. Следовательно, потребуется иметь физический массив как максимум на 260 элемен- тов. Тогда встает следующая задача: как логический массив отобра- зить на физический массив и как осуществлять к нему доступ? Ответ заключается в использовании списка индексов хеширования. Когда пользователь вводит формулу в электронную матрицу (ло- гический массив), адрес ячейки, задаваемый ее обозначением, ис- пользуется для поручения индекса небольшого физического массива. Предположим, что переменная "sheet" является физическим массивом. Индекс определяется на основе обозначения ячейки путем его преоб- разования в число, как было сделано в примере с массивом указате- лей. Затем это число делится на десять для получения начальной точки входа в массив. (Следует помнить, что для вашего примера физический массив составляет только десять процентов от логичес- кого массива). Если ячейка с этим индексом свободна, то в нее по- мещается логический индекс и значение. В противном случае возни- кает конфликт. Конфликт случается при получении во время хеширования двух одинаковых ключей. В этом случае полученный ин- декс будет соответствовать одному элементу физического массива. Следовательно, в массиве "sheet" делается поиск свободного эле- мента. Когда свободный элемент найден, в него помещается информа- ция, а указатель на это место будет помещен в исходный элемент. Это иллюстрируется на рис.17. Для поиска элемента в физическом массиве при заданном индек- се логического массива сначала делается преобразование логическо- го индекса в адрес, полученный посредством хеширования, и затем делается проверка физического массива на наличие в элементе с этим индексом требуемого значения. Если сравнение выполняется удачно, то информация найдена. В противном случае следует пройти по цепочке индексов до тех пор, пока не будет найдено нужное зна- чение или пока не будет обнаружен конец цепочки. Для того, чтобы понять, как эту процедуру можно применить к программе электронной таблицы сначала определим в качестве физи- ческого массива следующий массив записей: const SIZE = 260; type str9 = string[9]; str128 = string[128]; cell = record CellName: str9; formula: str128; next: integer; end; var sheet:array[0..SIZE] of cell; name: cell; Таблица Индекс Знач. След. Индекс в таблице +--------------------+ A1 ¦ A1 ¦ 100 ¦ 1 ¦0 +------+------+------¦ A2 ¦ A2 ¦ 200 ¦ 3 ¦1 +------+------+------¦ B19 ¦ B19 ¦ 50 ¦ -1 ¦2 +------+------+------¦ A3 ¦ A3 ¦ 300 ¦ -1 ¦3 +------+------+------¦ ¦ -1 ¦ 0 ¦ -1 ¦4 +------+------+------¦ ¦ -1 ¦ 0 ¦ -1 ¦5 +------+------+------¦ D2 ¦ D2 ¦ 99 ¦ -1 ¦6 +------+------+------¦ ¦ -1 ¦ 0 ¦ -1 ¦7 +------+------+------¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ +------+------+------¦ ¦ -1 ¦ 0 ¦ -1 ¦2597 +------+------+------¦ ¦ -1 ¦ 0 ¦ -1 ¦2598 +------+------+------¦ ¦ -1 ¦ 0 ¦ -1 ¦2599 +--------------------+ Предполагается, что в ячейке A1 значение 100, в A2 значение 200, в A3 - 300, в B19 - 50, а в D2 - 99. Рис.17. Пример хеширования. Перед использованием этот массив должен быть инициализиро- ван. Приводимая ниже процедура используется для установки поля обозначения ячейки на значение "empty" (пусто) для указания на отсутствие элемента. Значение -1 в поле следующего индекса озна- чает конец цепочки индексов хеширования. { инициализация физического массива } procedure InitSheet; var t:integer; begin for t := 0 to SIZE do begin sheet[t].CellName := 'empty'; sheet[t].next:= -1; end; end; { конец процедуры инициализации физического массива } В процедуре вставки делается обращение к функции HashIndex для вычисления индекса хеширования и помещения его в массив "sheet". Следует отметить, что если непосредственно полученное значение индекса хеширования указывает на занятую ячейку, то в процедуре выполняется поиск первого свободного места. Это делает- ся путем просмотра цепочки индексов хеширования до тех пор пока не будет обнаружена первая свободная ячейка. Когда свободная ячейка найдена, то делается запоминание значения логического ин- декса и значения элемента массива. Значение логического индекса требуется сохранить, поскольку он требуется при новом обращении к этому элементу. { вычисление индекса хеширования и вставка значения элемента } function HashIndex(i:str9):integer; var loc, temp, code:integer t :str9; begin loc := ord(i[1]-ord('A'); t := copy(i,2,9) val(t, temp, code) HashIndex := (loc*26+temp) div 10; end; { выполнение действительной вставки значения элемента } procedure Store(New:Cell); var loc, i:integer; begin loc := HashIndex(New.Cellname); if loc>SIZE then Writeln('Location out of bounds') else begin if ((sheet[loc].Cellname = 'empty') or (sheet[loc].Cellname = New.Cellname)) then begin sheet[loc].Cellname = New.Cellname; sheet[loc].formula = New.formula; end else { поиск свободной ячейки } begin { сначала просмотр до конца всей цепочки существующих индексов} while(sheet[loc].next <>-1) do loc := sheet[loc].next; { теперь поиск свободной ячейки } i := loc; while ((i |
(с)Все права защищеныПо всем интересующим вопросампрошу писать на электронный адрес |