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

2.3 Двусвязный список

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

struct имя_структурного_типа

{

элементы _структуры; /* данные */

struct имя_структурного_типа * указатель;

struct имя_структурного_типа * указатель;

};

beg

данные

Null

Начало списка

rex

. . .

. . .

L2

данные

L1

L2

данные

L1

L2

end

данные

L1

Null

(Последний элемент списка)

Рисунок 3 - Двусвязный список

Продемонстрируем некоторые особенности обработки двусвязных списков на примере рассмотренной выше задачи. Для работы с двусвязными списками будем, как и ранее, использовать три указателя : beg – на начало списка, end – на последний элемент, уже включенный в список и rex – указатель для “перебора” элементов списка. Приведенная ниже программа формирует двусвязный список для поставленной задачи.

#include <stdlib.h>

#include <stdio.h>

struct cell2 /*Определение структурного типа “звено двусвязного списка”*/

{char sign [10];

int weight;

struct cell2 * pc1; /* указатель на предшествующее звено */

struct cell2 * pc2; /* указатель на следующее звено */

};

void main()

{

struct cell2 * rex; /* Указатель для перебора звеньев списка: */

struct cell2 * beg=NULL; /* Начало списка */

struct cell2 * end=NULL; /* Конец списка */

printf("\nВведите значения структур:\n");

do /* Цикл ввода и формирования списка */

{ /* Выделить память для очередного звена списка: */

rex=(struct cell2 *)malloc(sizeof(struct cell2));

printf("sign=") ; /* Ввести значения элементов звена: */

scanf("%s",& rex->sign) ;

printf("weight=") ;

scanf("%d",& rex->weight);

if (rex->weight = = 0)

{

free(rex) ;

break; /* Выход из цикла ввода списка */

}

if (beg==NULL && end==NULL) /* Включить звено в список: */

beg=rex; /* Список пуст – включить введенный элемент в список первым*/

beg-> pc1= NULL; /* указатель на предшествующее звено для первого элемента списка равен NULL */

else /* Включить звено в уже существующий список */ ;

end->pc2=rex; /* Бывший последний ссылается на включенное звено */

rex-> pc1= end; ; /*Включенное звено ссылается на предшествующий элемент */

end=rex ; /*Включенное звено стало последним*/

end->pc2= NULL;

}

while(1) ; /* Конец ввода списка */

printf("\nСодержимое списка:") ; /* Напечатать список */

rex=beg;

while (rex!=NULL)

{

printf("\nsign=%s\tweight=%d",rex->sign, rex->weight) ;

rex=rex->pc2;

}

}

Обратите внимание на то, что вместо структур типа struct cell используется структурный тип struct cell2, имеющий дополнительное поле для второго указателя. Остальные особенности программы поясняются комментариями в тексте программы.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]