
3 семестр / Методические материалы / metodicheskie-ukazaniia-po-teme-20
.pdfНАЦИОНАЛЬНЫЙ ИССЛЕДОВАТЕЛЬСКИЙ ЯДЕРНЫЙ УНИВЕРСИТЕТ «МИФИ» |
|
Кафедра информатики и процессов управления (№17) |
|
Дисциплина «Информатика» (основной уровень), 2-й курс, 3-й семестр. |
|
Методические указания |
|
Тематическое занятие 20 |
|
Двусвязные линейные списки. |
|
Содержание |
|
Двунаправленные связи в списке............................................................... |
1 |
Основные определения......................................................................................... |
1 |
Организация связей............................................................................................... |
2 |
Двусвязный список........................................................................................ |
2 |
Указатели списка................................................................................................... |
2 |
Создание списка ..................................................................................................... |
2 |
Добавление элемента в список .......................................................................... |
3 |
Удаление элемента из списка ............................................................................. |
5 |
Двунаправленные связи в списке
Основные определения
Динамический линейный список называется двусвязным списком
(двунаправленный список, double-linked list, two-way list), если каждый его элемент с помощью двух указателей связывается с предыдущим и следующим элементами. При этом первый и последний элементы связаны только с одним элементом (следующим или предыдущим, соответственно).
Двусвязный линейный список становится кольцевым, если связать последний и первый элементы.
Двусторонняя очередь, которая также называется дек (deque — double ended queue), – частный случай линейного двусвязного списка, элементы которого можно добавлять и удалять как в начало, так и в конец.
Вобщем случае элементы линейного двусвязного списка можно добавлять
влюбое место и удалять из любого места списка.
1

Организация связей
В простейшем случае элемент линейного двусвязного списка должен состоять из трёх полей: информационного (inf) и двух указательных.
Назовем указательные поля prev (от previous – предыдущий) и next (следующий). Также часто используются названия left и right.
Схематичное изображение двусвязного линейного списка:
inf |
inf |
inf |
NULL |
prev |
prev |
next |
next |
next |
inf
prev |
next |
inf
prev |
NULL |
Соответствующее объявление:
typedef struct elem {
int inf; /* inf - информационное поле */
struct elem *prev; /* prev – указатель на предыдущий эл-т */ struct elem *next; /* next - указатель на следующий эл-т */
} Elem;
Двусвязный список
Указатели списка
Для создания двусвязного линейного списка и работы с ним необходимо иметь как минимум два указателя:
на начало списка (назовем его BegL, от begin of list),
на конец списка (назовем EndL – end of list).
Кроме того, потребуются дополнительные указатели: p – вспомогательный указатель, pk – указатель на некоторый k-й элемент списка.
Elem *BegL;
Elem *EndL; Elem *p, *pk;
Создание списка
1. Исходное состояние. |
|
|
||||
BegL |
|
EndL |
p |
BegL = NULL; |
||
|
|
|
|
|
|
|
NULL |
|
NULL |
|
|
? |
EndL = NULL; |
|
|
|
|
|
|
|
?
2

2. Выделение памяти под первый элемент списка и .
BegQ |
|
EndQ |
p |
||
|
|
|
|
|
p = (Elem *) malloc(sizeof(Elem)); |
NULL |
|
NULL |
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
? |
|
? |
? |
|
|
|
|
|
? |
? |
|
|
3. Занесение данных в первый элемент списка.
BegL |
|
EndL |
p |
|
|
|
|
|
|
NULL |
|
NULL |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
p->inf = 5; p->prev = NULL; p->next = NULL;
NULL |
NULL |
4. Установка указателей BegL и EndL на созданный первый элемент.
BegL |
|
EndL |
p |
||
|
|
|
|
|
BegL = p; |
|
|
|
|
|
|
|
|
|
|
|
EndL = p; |
5
NULL |
NULL |
Добавление элемента в список
Цель – добавление нового элемента после k-го.
1.Исходное состояние.
BegL
5 |
2 |
NULL |
prev |
next |
next |
pk |
EndL |
|
|
|
|
|
|
|
7 |
8 |
4 |
prev |
prev |
prev |
next |
next |
NULL |
p
?
?
3

2. Выделение памяти под новый элемент списка и заполнение его информационного поля.
BegL |
|
pk |
EndL |
|
|
|
|
|
|
|
|
|
|
|
5 |
2 |
7 |
8 |
4 |
NULL |
NULL |
p=(Elem*)malloc(sizeof(Elem)); p->inf = 3;
?
p
3 |
|
? |
|
? |
? |
|
3. Связывание нового элемента с (k+1)-м элементом.
BegL |
|
pk |
EndL |
|
|
|
|
|
|
|
|
|
|
|
5 |
2 |
7 |
8 |
4 |
NULL |
|
|
1 |
|
|
|
|
|
|
|
|
|
|
NULL |
|
|
|
p |
|
1pk->next->prev = p;
2p->next = pk->next;
?
3
?
2
4

4. Связывание нового элемента с k-м элементом.
BegL
5 |
2 |
NULL |
3p->prev = pk;
4pk->next = p;
pk |
EndL |
|
|
|
|
|
|
|
7 |
8 |
4 |
NULL |
4 |
p
3
3
5. Конечное состояние.
BegL |
|
pk |
|
p |
EndL |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
2 |
7 |
3 |
8 |
4 |
NULL |
NULL |
Удаление элемента из списка
Цель – удаление k-го элемента.
1. Исходное состояние.
BegL |
|
pk |
EndL |
|
|
|
|
|
|
|
|
|
|
|
5 |
2 |
7 |
NULL |
prev |
prev |
next |
next |
next |
8 |
prev |
next |
4
prev |
NULL |
5

2. Извлечение информации из удаляемого k-го элемента в переменную val.
BegL |
pk |
val |
EndL |
|
7 |
|
|
int val; |
|
|
||||
|
|
|
... |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
val |
= pk->inf; |
5 |
2 |
7 |
8 |
4 |
NULL |
NULL |
3. Связывание (k–1)-го элемента с (k +1)-м элементом.
BegL |
|
|
pk |
|
|
val |
|
EndL |
|
|
|
|
|
|
|
||||
|
|
|
|
|
|
7 |
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
|
2 |
7 |
8 |
4 |
NULL |
NULL |
1
1 pk->prev->next = pk->next; 2 pk->next->prev = pk->prev;
4. Освобождение памяти удаляемого k-го элемента.
BegL |
pk |
val |
EndL |
|
7 |
free(pk); |
|
5 |
2 |
7 |
8 |
4 |
NULL |
NULL |
5. Конечное состояние. |
|
|
|
|
|
|
|
|||||
|
BegL |
|
|
pk |
|
|
|
|
|
|
val |
|
|
|
|
|
|
|
EndL |
|
|||||
|
|
|
|
|
|
7 |
||||||
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
? |
|
|
|
|
||||
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
? |
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
|
2 |
|
|
8 |
4 |
|
|
|
NULL |
NULL |
6