Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
DSD_Spiskovye_struktury_dannykh_na_baze_massivo...doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
2.59 Mб
Скачать

2.1.19Продолжение. Представление однонаправленных списков массивами указателей

В предыдущих разделах, при реализации однонаправленных списков массивами указателей на элементы списка, для хранения служебной информации о размере массива и о размере списка используются две специальные фиксированные области (записи) – размер выделенного массива указателей на элементы списка и реальное количество элементов списка. Это не всегда удобно, особенно если нетипизированный файл используется для представления нескольких списков. Действительно в последнем случае растет количество таких областей, что усложняет работу с программой. И принципиально это невозможно, если число списков заранее не известно.

Возможным альтернативным решением является хранение служебной информации о массиве указателей в самом массиве. Предпосылками к этому является то, что пространство, отводимое в нетипизированном файле под массив указателей, является соответствующим блоком байт. А уже затем этот блок или его части считываются в переменные определенных типов. Но тогда переменные, в которые считывается конкретный блок, могут иметь разные типы. Следовательно, по мере необходимости разные участки массива указателей могут считываться в переменные разных типов. Такая техника работы с нетипизированным файлом, а следовательно и с массивом, хранящимся в этом файле, позволяет по-разному рассматривать разные его части.

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

В рамках конкретной программы обработки списков весь выделяемый массив байт рассматривается как состоящий из двух смежных частей. Первая часть массива содержит служебную информацию - два элемента типа int, соответственно общий размер массива и фактическое количество элементов списка. А вторая часть массива используется для хранения указателей – элементы типа int, на узлы (элементы) списка.

Таким образом, начальная структура файла приобретает следующий вид:

№ бт

0  3

4  7

Массив указателей на элементы списка

M

8  8 + 2*4 + N*4 - 1

Заголовок списка "дыр"

Указатель на массив указателей на элементы списка

Размер массива указателей N

Количество элементов списка K

Указатели на элементы списка

Рисунок 2.8 – Структура файла со списком на базе массива указателей после инициализации

Блок из первых 4 байт - условно запись №0, зарезервирован под заголовок списка дыр. Второй блок из 4 байт - условно запись №1, зарезервирован под указатель на массив указателей на элементы списка.

Массив указателей на элементы списка первоначально располагается, начиная с байта №8, и занимают блок байт размером 2*4 + N*4, где первые 2*4 байт занимают соответственно поле размер массива указателей - максимально возможное количество элементов списка N, и поле количество элементов списка К.

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

Обобщенная структура массива указателей имеет вид – Рисунок 2.9:

Индекс

N+1

Незанятая часть массива

K+2

Указатель K ->

K+1

. . .

Указатель 2 ->

+3

Указатель 1 ->

+2

Количество элементов в списке K

+1

PtrBase ->

Размер массива N

0

Рисунок 2.9 – Структура массива указателей, содержащего служебную информацию

где PtrBase - указатель на начало модифицированного массива указателей.

Однако при таком решении приходится специально следить за правильностью обработки начальных элементов массива – элементы с индексами 0 и 1, и остальных элементов массива – элементы с индексами от 2 до N-1. Это влечет усложнение текста соответствующих функций.

Во избежание отмеченного усложнения можно предложить ввести другой, назовем его действующий указатель PtrV, который будет ссылаться не на начало массива указателей, а на местоположение в этом массиве первого указателя на элемент списка. Именно действующий указатель будет заноситься в область файла, содержащую указатель на массив указателей на элементы списка.

Обобщенная структура массива указателей теперь будет имеет вид:

Индекс

N+2

Незанятая часть массива

K

Указатель K ->

K-1



Указатель 2 ->

+1

PtrV ->

Указатель 1 ->

0

Количество элементов в списке K

-1

PtrBase ->

Размер массива М

-2

Рисунок 2.10 – Структура массива указателей, содержащего служебную информацию и с индексацией указателей начиная с нуля

Теперь можно считать, что указатель на первый элемент списка имеет индекс 0, а элементы служебной информации имеют отрицательные значения индексов: ‑1 и –2.

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

Отличие будет только в работе с элементами служебной информации списка. Изменения коснутся следующих функций:

  • инициализация файла со списком;

  • открытие файла со списком;

  • корректировка счетчика элементов списка;

  • увеличение размера массива указателей на элементы списка;

  • удаление списка с усечением файла;

  • добавление элемента в список;

  • удаление элемента из списка;

  • поиск элемента.

Рассмотрим пример работы со списком в файле для случая, когда в файле может располагаться не один список, а несколько. В таком случае не удобно (а иногда и не возможно) использовать глобальные переменные, содержащие количество элементов списка CntElmLst и текущий размер массива SizeAr, значение которых инициализировались при открытии файла, потому что для каждого списка эти переменные имеют разные значения. Теперь в самих функциях работы со списком из массива указателей будут извлекаться значения количества элементов списка и размер массива указателей.