
Тема: Списки
Односвязный линейный список – это совокупность элементов, содержащих два поля: поле D – запись с данными и поле F – указатель «вперед», то есть, адрес следующего элемента. При этом адрес последнего элемента – нулевой.
PB
– указатель начала (Дескриптор)
D
F D
F D
F D
Nil
…
Дескриптор списка содержит имя списка PB, количество элементов, описание структуры элементов и т.д.
Для доступа к элементу списка необходим просмотр списка с головы (такой доступ называется последовательным), что, естественно, медленно. Если сделать список кольцевым, то начинать просмотр можно с любого элемента, после доступа к нужному элементу в PB заносится адрес его последователя.
Главные операции над списками
Вставка элемента в список;
Исключение элемента из списка.
Вставка элемента с адресом N в односвязный список после элемента UK:
UK
D F
D F D F
N
;
F(N) F(UK);
F(UK) N;
Вставка же элемента в список перед указанным элементом сложна, так как элемент содержит указатель вперед. Можно предложить такой вариант:
обменять местами поле данных в элементах с адресами UK и N, а затем вставить элемент N:
Исключение элемента, стоящего после элемента UK из односвязного списка:
IF F(UK) <> Nil
THEN
P F(UK) {запоминаем адрес исключаемого элемента}
F(UK) F(P) {изменяем адрес указателя элемента с адресом
UK}
ELSE {исключение невозможно, так как список пуст}
Часто удаленный элемент включается в начало списка свободных элементов, для этого:
F(P) E;
E P;
UK P
D F D F D F
F
D F D F D
E
При использовании списковых структур в системе создается не менее двух списков: включенных элементов (функциональный список с информацией) и исключенных (свободных элементов), причем второй – один на все существующие в программе списки. Например:.
500 520 540Дескриптор
функциональных списков
(дескриптор
00 – список пуст)
10 0 0
1000 0 0 1000 1010 1090 50
Свободная память для элементов списка
4 3 3 1040 1010 1070 500 520 540
Физически участки памяти в списках
перемешаны:
1000 1010 1070 1040 1080 1090
0 1030 0 1080 1060 1020 1090 1050 0 1000
Двусвязные линейные список
Часто в линейном списке необходимо продвигаться в двух направлениях. Тогда делается двусвязный список, в котором каждый элемент имеет два указателя: вперед (F) и назад (B). В структуру этого списка добавляется указатель конца (PE). Начало и конец в этом списке логически эквивалентны, так как доступ к элементу списка имеется с любого конца.
РВ Дескриптор РЕ
vb
Nil F D B F D B F D B Nil D…
Для
построениякольцевого
двусвязного списка
необходимо объединить два пустых
указателя, тогда указатель конца не
нужен, а указатель начала может быть,
вообще говоря, в любом месте:
РВ Дескриптор В F D B F D
B F D B F D
…
…
Включение элемента в двусвязный список
а) перед элементом, находящимся по адресу UK:
UK
B(N)
B(UK)
B
B F D B F D(UK)
N
F(N)
UK
F(B(N)
N
B F D
N
б) после элемента, находящегося по адресу UK:
F(N) F(UK)
B(N) UK
B(F(UK) N;
F(UK) N;
Удаление элемента по адресу UK в двусвязном списке:
B F D B F D B F D
B(F(UK)) B(UK)
F(B(UK)^ F(UK)
Операции, которые мы имеем право выполнять с линейными списками, включают следующие:
Получить доступ к k-му узлу списка, чтобы проанализировать и/или изменить содержимое его полей.
Объединить два (или более) линейных списка в один список.
Разбить линейный список на два (или более) списка.
Сделать копию линейного списка.
Определить количество узлов в списке.
Выполнить сортировку узлов списка в возрастающем порядке по некоторым полям в узлах.
Найти в списке узел с заданным значением в некотором поле.
Списки удобно создавать сразу упорядоченными, вставлять элементы не нарушая упорядоченности. При сортировки можно менять данные, а можно- указатели.
При работе со списками отслеживать: вставку в пустой список, в начало списка, в конец списка