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

3.7. Контрольные вопросы по теме

  1. В чем состоит отличие списковых структур от стека и очереди?

  2. Что включает в себя стандартный набор операций со списком?

  3. В чем состоит простейший способ реализации списка с помощью массива?

  4. Как выполняется вставка элемента при простейшей реализации списка на базе массива?

  5. Как выполняется удаление элемента при простейшей реализации списка на базе массива?

  6. В чем состоят преимущества и недостатки простейшего способа реализации списков с помощью массивов?

  7. За счет чего можно повысить эффективность простейшей реализации списка с помощью массива?

  8. В чем смысл реализации статического списка с указателями-индексами?

  9. Какую структуру имеют элементы массива при статической реализации списка?

  10. Какие описания необходимы для статической реализации списка?

  11. Как выполняется проход по статическому списку?

  12. Как выполняется поиск элемента в статическом списке?

  13. Какие особые ситуации возможны при статической реализации списка?

  14. Что такое пустой статический список?

  15. Как выполняется добавление элемента после заданного в статическом списке?

  16. Как выполняется добавление элемента перед заданным в статическом списке?

  17. Как выполняется удаление элемента в статическом списке?

  18. Как в простейшем случае можно отслеживать свободные ячейки массива при реализации статического списка?

  19. В чем недостатки простейшего способа отслеживания свободных ячеек при реализации статического списка?

  20. Как используется вспомогательный список свободных ячеек при статической реализации списка?

  21. Как инициализируется вспомогательный список свободных ячеек при создании пустого статического списка?

  22. Что является основой реализации динамических списков?

  23. Какую структуру имеют элементы динамического списка?

  24. Какие описания необходимы для реализации динамического списка?

  25. Какие переменные используются для реализации операций с динамическими списками?

  26. Что включает в себя создание пустого динамического списка?

  27. Как выполняется проход по динамическому списку?

  28. Как выполняется поиск элемента в динамическом списке?

  29. Как выполняется удаление элемента в динамическом списке?

  30. Как выполняется добавление элемента после заданного в динамическом списке?

  31. Как выполняется добавление элемента перед заданным в динамическом списке?

  32. Какие особенности возникают при обработке упорядоченных списков?

Тема 4. Усложненные списковые структуры

4.1. Двунаправленные линейные списки

Недостатком рассмотренных выше списковых структур является их однонаправленность от первого элемента к последнему. Если при обработке списков часто бывает необходимо переходить от текущего элемента к его предшественнику, то такая односторонняя организация становится неудобной. Выходом является построение двунаправленных списков, в которых каждый элемент “знает” обоих своих соседей, как левого, так и правого.

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

Элем. 1

правый

левый

Элем. 2

правый

левый

Элем. 3

правый

левый

Элем. N

правый

левый

. . .

А

pHead

налогично обычным спискам, удобно ввести фиктивный заголовочный элемент, а поскольку двунаправленные списки являются симметричными, удобно сделать их замкнутыми, кольцевыми: правая ссылка последнего элемента указывает на заголовок, а левая ссылка заголовка – на последний элемент. Адрес заголовка определяется указателемpHead.

заголовок

правый

левый

Элем. 1

правый

левый

Элем. 2

правый

левый

Элем. N

правый

левый

Элем. 1

правый

левый

. . .

Отметим достоинства и недостатки двунаправленных списков. Достоинство – простота перехода от текущего элемента к любому его соседу. Недостатки – увеличиваются затраты памяти и число операций на поддержку дополнительного указателя.

Двунаправленный список можно реализовать как на основе массива (причем – обеими способами), так и динамически.

В последнем случае описание структуры данных выглядит следующим образом:

type pDin2Item = ^ TDin2Item; {ссылочный тип}

TDin2Item = record {базовый тип}

inf : <тип информационной части>;

left, right : pDin2Item; {адреса соседних элементов}

end;

Если pHead есть указатель на заголовок, то пустой список создается так:

  • выделяется память под заголовок, адресуемая указателем pHead

  • оба ссылочных поля заголовка устанавливаются в адрес самого заголовка: pHead^.left := pHead; pHead^.right := pHead;

(при этом пустая ссылка nil нигде НЕ используется!)

Набор операций расширяется просмотром и поиском не только в прямом, но и в обратном направлениях. Немного изменяется условие достижения конца списка – вместо условия появления пустой ссылки надо использовать условие получения на текущем шаге адреса заголовка. Например, проход в обратном направлении реализуется так:

  • устанавливаем начальное значение указателя текущего элемента на последний элемент списка: pCurrent := pHead^.left;

  • организуем цикл прохода до достижения заголовка

while pCurrent <> pHead do pCurrent := pCurrent^.left;

У

pCurrent

даление заданного элемента требует изменения большего числа ссылочных полей. Надо изменить правый указатель у левого соседа удаляемого элемента и левый указатель у правого соседа.

Левый сосед

right

left

Удаляемый элем.

right

left

Правый сосед

right

left

Если удаляемый элемент адресуется указателем pCurrent, то pCurrent^.left определяет адрес левого соседа, а pCurrent^.right – адрес правого соседа. Тогда необходимые изменения реализуются так:

pCurrent^.left^.right := pCurrent^.right;

pCurrent^.right^.left := pCurrent^.left;

Аналогично выполняется добавление нового элемента, например – после заданного указателем pCurrent. Пусть как обычно новый элемент определяется указателем pTemp. Тогда для вставки его в список надо настроить оба его ссылочных поля, изменить правое ссылочное поле у текущего элемента и левое ссылочное поле у его правого соседа.

текущий элем.

right

left

Правый сосед

right

left

новый элем.

right

left

pTemp

pCurrent

Необходимые присваивания (порядок следования важен!):

pTemp^.right := pCurrent^.right;

pTemp^.left := pCurrent;

pCurrent^.right^.left := pTemp;

pCurrent^.right := pTemp;

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