Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Методичка по лабораторной работе №2.doc
Скачиваний:
41
Добавлен:
02.05.2014
Размер:
108.03 Кб
Скачать

2.2.Рекурсия при обработке двусвязного списка.

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

struct cell2*end; /* Объявление глобальной переменной-указателя на последний элемент списка */

/* Определение структурного типа "Звено двусвязного списка";*/

struct cell2

{

char sign[10] ;

int weight;

struct cell2 * рс1;

struct cell2 * рс2

};

#include <stdlib.h>

#include <stdio.h>

/* Функция ввода и формирования двусвязного списка: */

struct cell * input(struct cell2 * r)

{

struct cell * p;

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

printf("sign=") ;

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

printf("weight=") ;

scant("%d",& p->weight) ;

if (р -> weight == 0) {

free (p) ; end = r; /* Формирование указателя на последний элемент списка*/

return NULL;

}

р -> рс1 = r; /* Формирование указателя на предшествующий элемент */

р -> рс2 = input(p); /* Рекурсивный вызов. Формирование указателя на следующий элемент */

return p; /* Возвращается адрес включенного в список элемента*/

}

/* Функция "печати" двусвязного списка; */

void output(struct cell2 *p)

{

if (p == NULL)

{

printf("\nCписок исчерпан! ");

return;

}

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

output(p -> рс2); /* Рекурсивный вызов */ }

void main()

{

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

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

beg=input(beg); /* Ввод списка. */

/*Напечатать список: */

printf("\nСодержимое списка:");

output(beg) ;

}

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

struct cell * input(struct cell2 * r);

указывающий на наличие аргумента. При рекурсивном вызове значением аргумента является ссылка на последний включенный в список элемент (последним этот элемент является только в текущий момент времени). Этот адрес-ссылка необходим для заполнения поля указателя на предыдущее звено списка при формировании следующего звена. Комментарии в тексте программы поясняют остальные особенности обработки двусвязных списков.

Функция рекурсивного просмотра и печати списка имеет прототип

void output(struct cell2 *p). Здесь отличий еще меньше: использование структурного типа struct cell2 и указателя на следующее звено p -> рс2 вместо (p -> рс для односвязного списка.

Обратите внимание на наличие кроме указателя begдополнительно указателяend, объявленного как глобальная переменная. Этот указатель ссылается на последний элемент списка. Наличие двух указателей объясняется особенностями двусвязного списка: в нем обязательно наличие указателей как на начало, так и на конец списка. Значение указателяend формирует функцияoutput() при каждом рекурсивном вызове функции. В качестве значения указателяendвыступает адрес последнего сформированного звена списка (последним этот элемент является только в текущий момент времени). При завершении работы функцииoutput() в указателеend окажется адрес завершающего (физически последнего) элемента списка. Вышеописанные отличия формирования двусвязного списка проявляются и в основной функцииmain, что видно из приведенной программы.

Результаты выполнения программ для варианта двусвязного списка не будут отличаться от результатов выполнения программы для односвязного списка.