|
Новости |
Применение массива указателей для организации разреженных массивовПредположим, что электронная матрица имеет размеры 26х100 /с А1 по Z100/ и состоит всего из 2 600 элементов. Теоретически мож- но использовать следующий массив записей: str9 = string[9]; str128 = string[128]; CellPointer = CellPointer; cell = record CellName:str9; formula:str128; end; var pa:array[1..2600] of cell; Однако, 2 600 ячеек, помноженные на 128 (размер одного поля для формулы), потребует 332 800 байт памяти под довольно неболь- шую электронную таблицу. Такой подход, очевидно, нельзя использо- вать на практике. В качестве альтернативы можно использовать мас- сив указателей записей. В этом случае потребуется значительно меньше памяти, чем при создании всего массива. Кроме того, произ- водительность будет значительно выше, чем при использовании свя- занного списка или дерева. Для этого метода данные описываются следующим образом: type str9 = string[9]; str128 = string[128]; cell = record CellName:str9; formula:str128; end; var sheettarray[1..10000] of CellPointer; Этот массив меньшего размера можно использовать для содержа- ния указателей на информацию, введенную пользователем в электрон- ную матрицу. При вводе каждого элемента указатель на информацион- ную ячейку помещается в соответствующее место массива. Рис.16 иллюстрирует структуру памяти, когда разреженный массив строится на основе массива указателей. a +--------------------------------------+ ¦ ¦1nil¦ ¦1nil¦ ¦1nil¦ ¦ +-+--------+-------------------------+-+ ¦ ¦ ¦ +--------------+ ¦ ¦ +---¦2info for A[n]¦ ¦ ¦ +--------------+ ¦ ¦ ¦ ¦ +---------------+ ¦ +-- ¦2 info for A[a]¦ ¦ +---------------+ ¦ +---------------+ +---¦2 info for A[l]¦ +---------------+ Рис.16. Использование массива указателей для организации раз- реженного массива: 1 - нулевое значение указателя; 2 - информационные поля соответс- твующего элемента. Перед первым использованием массива указателей необходимо каждый элемент установить в нулевое значение, что означает от- сутствие элемента в этой позиции. Используйте следующую функцию: procedure InitSheet; var t:integer; begin for t := 1 to 10000 do sheet[t] := nil; end; { конец блока инициализации } Перед написанием процедуры вставки следует запрограммировать функцию поиска индекса. Эта функция находит соответствующий ин- декс массива указателей по заданному названию ячейки. При поиске индекса предполагается, что все названия начинаются с большой буквы, за которой идет некоторое число, например, В34, С19 и т.д. Эта функция приводится ниже на следующей странице. Эта функция позволяет при реализации процедуры вставки { эта функция определяет индекс указанной ячейки } function FindIndex(i: CellPointer): integer; var loc,temp,code:integer; t:str9; begin loc := ord(i^.CellName[1]); t := copy(i^.CellName,2,9); val(t,temp,code); loc := loc+(temp*20); find := loc; end; { конец функции поиска индекса } соответствующую позицию массива указателей для каждой ячейки. Как видно, поиск нужного индекса выполняется просто и быстро, так как нет необходимости выполнять последовательный просмотр. Этот метод иногда называют прямым хешированием, поскольку индекс ячейки па- мяти определяется непосредственно по заданному элементу. Когда пользователь вводит формулу для ячейки, то эта ячейка /которая задается своим обозначением/ задает индекс массива указателей "sheet". Индекс определяется по обозначению ячейки путем его пре- образования в число с помощью функции FindIndex. Вставка осущест- вляется с помощью следующей процедуры: procedure Store(New: CellPointer); var loc:integer; begin loc := FindIndex(New); if loc>10000 then WriteLn('Location out of bounds') else sheet[loc] := New; end; { конец процедуры вставки } Поскольку каждая ячейка имеет уникальное обозначение, она будет иметь также уникальный индекс. Поскольку используется стан- дартная кодировка символов, указатель каждого элемента будет пра- вильно помещен в массив. Если вы сравните эту процедуру с вариан- том для связанного списка, то вы обнаружите, что она значительно короче и проще. Функция удаления также выглядит короче. При вызове этой функции задается индекс ячейки и возвращается указатель элемента. Кроме того, освобождаемая память возвращается системе: { удаление ячейки из массива } procedure Delete(r_cell: CellPointer); var loc:integer; begin loc := FindIndex(r_cell); if loc>10000 then WriteLn('Cell out of bounds') else begin Dispose(r_cell); sheet[loc]:=nil; end; end; { конец процедуры удаления } Если вы сравните эту процедуру с версией, использующей свя- занный список или дерево, то обнаружите, что она значительно про- ще и выполняется быстрее. Следует помнить, что сам массив указателей требует некоторо- го дополнительного расхода памяти под каждую ячейку. В некоторых случаях это является серьезным ограничением. |
(с)Все права защищеныПо всем интересующим вопросампрошу писать на электронный адрес |