Форма представления структур данных в памяти ЭВМ зависит от предполагаемого использования данных, поскольку для различных типов структур эффективность выполнения тех или иных операций обработки данных различна. Элементы структуры данных в памяти ЭВМ могут адресоваться двумя способами - по месту или по содержимому. В первом случае указываются логические или физические адреса данных, определяющие место расположения данных в памяти машины. Во втором случае размещение данных и их выборка осуществляются по известному значению ключа, т.е. определяются содержимым самих данных. Этот случай реализуется в специальной ассоциативной памяти ЭВМ. Некоторый аналог ассоциативной памяти может быть реализован средствами специального программного обеспечения в обычной памяти ЭВМ.
Наиболее простой формой хранения данных в памяти ЭВМ является одномерный линейный список, обеспечивающий линейное упорядочение элементов данных (вектора данных). Это удобно и с точки зрения свойств оперативной памяти ЭВМ. Здесь байты упорядочены по возрастанию их адресов от 0 до наивысшего (проидентифицированы адресом), образуя вектор памяти.
Отображение логической структуры данных на физическую структуру хранения называют адресной функцией. При реализации адрес-Ной функции использует два основных метода: последовательное распределение памяти; связное распределение памяти.
При последовательном распределении узлы линейного списка размещаются в последовательных элементах памяти и адрес каждой записи можно вычислить с помощью адресной функции
,
где i - индекс элемента (i= 1,N); b - адрес базы начала вектора в памяти; m - размер элемента (записи) списка.
С помощью линейного списка при последовательном распределении памяти можно реализовать регулярное двоичное дерево (рис. 9.1).
По дереву, которое при этом получается, можно двигаться в обоих направлениях, так как от узла yк можно перейти к его потомкам, удвоив k (или удвоив k и прибавив единицу). Можно двигаться к узлу, являющемуся исходным для уk, разделив k пополам и отбросив дробную часть.
Адрес
Содержимое
a(1) = b
Y1
a(2) =b+m
Y2
a(3) =b+2m
Y3
a(4) =b+3m
Y4
a(5) =b+4m
Y5
a(6) =b+5m
Y6
a(7) =b+6m
Y7
Рис. 9.1. Пример реализации регулярного двоичного дерева
с помощью линейного списка
Другой способ размещения в памяти сбалансированного (регулярного) двоичного дерева заключается в следующем. Если для представления двоичного дерева используется вектор памяти от элемента i до элемента j включительно, то корень дерева размещается в элементах памяти с адресом g= [(i+j)/2], где знак [] обозначает округление до ближайшего меньшего целого.
Корень дерева размещается в середину вектора. В элементах памяти от i-го до (m-1)-го включительно размещается левое поддерево. В элементах памяти от (m+1)-го до j-го включительно размещается правое поддерево. Аналогично процесс повторяется для размещения каждого поддерева. При этом корень левого поддерева размещается в элемент (квант) gп = [i+(g - 1)]/2, а корень правого поддерева в элемент gп = [(g + 1) + j]/2. Адреса элементов вычисляются по формуле a( g) = b+ (g -1)m.
При связном распределении памяти (связные списки) задаются отношения следования и предшествования элементов с помощью указателей. Указателями служат адреса, хранимые в записях данных. В связных списках значение адресной функции можно получить только путем просмотра хранящихся указателей.
Связанное распределение - более сложный, но и более гибкий способ хранения линейного списка. Здесь не требуется, чтобы список хранился в последовательных элементах памяти, а линейная структура списка (цепи) обеспечивается указателями (рис. 9.2). Окончание списка кодируется (обозначается) специальным шифром, например, NIL или ^.
Рис. 9.2. Пример связанного линейного списка
Частными случаями линейного связного списка являются стек, очередь, дек. В стеке записи вводятся и удаляются только с одного конца. Стековую структуру еще называют структурой с магазинной памятью (последним пришел, первым ушел), а также LIFO-cписком. Стек имеет один конец и для него требуется всего один указатель.
Очередь представляет собой список, у которого добавление записей ведется на одном конце, а извлечение (удаление) - на другом. Такую структуру еще называют FIFI-списком (первая поступившая запись первой и выбирает). Очередь предполагает использование двух указателей: один не удаление, другой на добавление записи (узла).
Дек - логическая структура, в которой удаление и добавление узлов происходит на обоих концах.
Для достижения большей гибкости при работе с линейными списками в каждый узел X[i] вводятся два указателя. Один из указателей реализует связь X[i] с узлом X[i+1], а другой с узлом X[i-1] (рис. 9.3).
Рис. 9.3. Пример двунаправленного линейного списка
Удобством связанных списков является то, что при изменении порядка записей, сокращении или расширении вектора данных не требуется перемещение записей в памяти ЭВМ. Достаточно лишь изменить значения полей связи (указателей). Однако доступ к конкретному узлу может сказаться намного длительнее, чем при последовательном распределении памяти (т.к. надо просмотреть все предшествующие узлы). Компромиссом является организация связанного линейного списка с пропусками (рис. 9.4).
Для этого линейный список делится на группы узлов, связанные между собой обратными указателями. Вначале осуществляется доступ по обратным указателям к группе, в которой находится требуемый узел, а затем по прямым указателями перебираются узлы группы, пока не будет найден требуемый узел. Вход в список при таком способе организации осуществляется с конца.
Другой способ (рис. 9.4) заключается в построении специального дополнительного списка - индекса, например, с последовательным распределением памяти. Элементы индекса - значения первых узлов каждой группы и указатели на них.
а)
б)
Рис. 9.4. Способы ускорения доступа к узлам линейного связанного списка: а) организация линейного списка с пропусками; б) то же с использованием индекса
Оптимальный размер группы при равновероятном нахождении узла в любой из групп: nг = Ön , где n - количество элементов списка. Число групп: l = [ n/nг ].
При равновероятном нахождении узла в любой из групп при доступе к узлу необходимо просмотреть в среднем l/2 групп, а в каждой группе nг/2 узлов. Следовательно, общее количество просмотров
А = l/2 + nг /2 = 0.5 ( [n/nг] + nг ).
Разновидностью представления в памяти линейного списка является циклический список(кольцевая структура, кольцо), который обладает той особенностью, что связь от последнего узла идет к первому узлу списка. Это позволяет получить доступ к любому узлу списка, отправляясь от любого заданного узла. Иногда используют двунаправленные циклические списки (рис. 9.5).
В ряде случаев удобно использовать циклический список с указателями на голову списка из каждого узла. Связанные линейные списки позволяют реализовать в памяти ЭВМ и более сложные нелинейные структуры, в частности, древовидные и сетевые. Такие представления структур называются многосвязанными списками (несколько указателей).
Основой построения связанных списковых структур являются указатели. Практически используются три типа указателей: машинный (действительный); относительный; символьный (идентификатор). Машинный тип указателей дает жесткую привязку записей к конкретному месту памяти, но обеспечивает наибольшую скорость обработки данных. Относительный адрес (указатель) позволяет размещать записи в любом месте памяти и на различных внешних устройствах без изменения значений указателей, при этом относительное расположение в памяти узлов списка между собой должно оставаться постоянным. При перемещении списка меняется только базовый адрес памяти. Относительный адрес в качестве указателей применяются при страничной организации памяти.
Символические адреса (идентификаторы) позволяют перемещать отдельные записи относительно друг друга, включать или удалять записи в список без изменения указателей во всех остальных записях списка. Однако скорость доступа здесь наименьшая. Такие указатели удобно использовать для интенсивно меняющихся файлов.
Различают встроенные указатели и справочник указателей. Если указатели образуют часть записи, то они называются встроенными. Если указатели хранятся отдельно от записей, то они образуют справочник.