Лабораторная работа №2
Методические указания к лабораторной работе
“создание списковых структур данных”
по дисциплине “технология программирования”
1 Цель работы
Усвоение студентами рекурсивных процедур программирования на примере создания списков данных.
2 Краткие теоретические сведения
Во многих задачах требуется использовать данные, представление которых (конфигурация, размеры, состав) может изменяться в процессе выполнения программы. О таких изменяемых данных говорят, используя принятый в информатике термин "динамические информационные структуры ". Динамические структуры имеют следующие основные особенности:
непостоянство и непредсказуемость размера (числа элементов) структуры в процессе ее обработки. Число элементов структуры может изменяться от нуля до значений, определяемых спецификой решения задачи или доступным размером памяти;
отсутствие физической смежности элементов структуры в физической памяти. Логическая последовательность элементов задается в явном виде с помощью одного или нескольких указателей или связок, хранящихся в самих элементах. Следовательно, память, занимаемая динамической структурой, не является непрерывной и может быть хаотически разбросана в области памяти.
Часто динамические структуры физически представляются в форме связных списков. Связный список – такая структура данных, элементами которой служат записи с одним и тем же форматом, связанные друг с другом с помощью указателей, хранящихся в самих элементах списка.
2.1 Односвязный список
Наиболее простая динамическая информационная структура - это односвязный список, элементами (звеньями) которого служат объекты, например, такого структурного типа:
struct имя_структурного_типа
{
элементы _структуры; /* данные */
struct имя_структурного_типа * указатель;
};
В каждую структуру такого типа входят: содержательные элементы структуры которые хранят информацию об однотипных объектах предметной области ( будем их называть просто ”данные” и обозначать D), и указатель на другой объект того же типа, что и определяемая структура ( будем обозначать эту часть структуры L).
Чтобы продемонстрировать некоторые особенности обработки простых динамических информационных структур, разработаем программу, в которой определим структурный тип для представления звеньев односвязного списка и решим такую простейшую задачу: "Ввести с клавиатуры произвольное количество структур, объединяя их в односвязный список, а затем вывести на экран дисплея содержимое введенного списка в порядке формирования его звеньев".
Анализ динамических информационных структур удобнее всего выполнять с помощью их графического изображения. На рисунке 1 приведены схема односвязного списка и обозначения, которые будут использованы в программе. Для работы со списком понадобятся три указателя: beg - на начало списка; end - на последний элемент, уже включенный в список; rex - указатель для "перебора" элементов списка от его начала.
Начало списка
beg
. . .
rex
. . .
end
(Последний элемент
списка)
Рисунок 1. Односвязный динамический список
Содержательные данные списка представляют собой наименование объекта и его вес. Признаком окончания содержательной информации при ее вводе является нулевое значение веса. Следующая программа решает сформулированную задачу.
#include <iostream>
#include <conio.h>
using namespace std;
//описание структуры "Звено списка"
struct cell
{ char sign[10];
int weight;
cell *pc;
};
void main()
{ cell *rex; //указатель для перебора звеньев списка
cell *beg = NULL; //начало списка
cell *end = NULL; //конец списка
cout << "Input value struct\n"; //введите значения списка
//цикл ввода и формирования списка
do
{ //выделить память для очередного звена списка
cell *rex = new cell;
//ввести значения элементов звена
cout << "sign = ";
cin >> rex->sign;
cout << "weight = ";
cin >> rex->weight;
if(rex->weight == 0)
{ delete [] rex;
break; //выход из цикла ввода списка
}
//включить звено в список
if(beg == NULL && end == NULL)
beg = rex; //список пуст - включить введенный элемент в список первым
else
end->pc = rex; //включить звено в уже существующий список
end = rex;
end->pc = NULL;
}
while(1); //конец ввода списка
//напечатать список
cout << "\nContent of list"; //Содержимое списка
rex = beg;
while(rex != NULL)
{ cout << "\nsign = " << rex->sign
<< "\tweight = " << rex->weight;
rex = rex->pc;
}
getch();
}
Пример выполнения программы:
Введите данные о структурах:
Sign=sigma
weight=16
Sign=omega
weight=44
Sign=alfa
weight=0
Содержимое списка:
Sign=sigma weight=16
Sign=omega weight=44
Обратите внимание, что при вводе данных о третьем элементе списка введено нулевое значение переменной weight и соответствующий элемент в список не включен.
В программе ввод данных, т.е. заполнение односвязного списка структур, выполняется в цикле. Условием окончания цикла служит нулевое значение, введенное для элемента int weight очередной структуры.
Формирование списка структур происходит динамически. Указатели-beg, end инициализированы нулевыми значениями - вначале список пуст.
Обратите внимание на преобразование типов (struct cell *) при выделении памяти для структуры типа struct cell. Функция malloc() независимо от типа параметров всегда возвращает указатель типа void *, а слева от знака присваивания находится указатель rex типа struct cell *. Используется явное приведение типов, хотя это не обязательно - тип void * совместим по операции присваивания с указателем на объект любого типа.
Остальные особенности программы поясняются комментариями в ее тексте.