- •Методические указания к лабораторной работе
- •2.1 Односвязный список.
- •2.2.Рекурсия при обработке односвязного списка.
- •Все-если
- •2.3 Двусвязный список
- •2.2.Рекурсия при обработке двусвязного списка.
- •3 Методика выполнения лабораторной работы
- •4 Содержание отчета
- •5 Литература
- •6 Рекомендуемые задания к лабораторной работе
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, что видно из приведенной программы.
Результаты выполнения программ для варианта двусвязного списка не будут отличаться от результатов выполнения программы для односвязного списка.