ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 19.04.2024
Просмотров: 157
Скачиваний: 0
Содержание
1.Введение__________________________________________________3
2. Связные линейные списки__________________________________3
3. Машинное представление связных линейных списков_________4
4. Структура двухсвязного списка______________________________4
5. Реализация операций над связными линейными списками______5
- Перебор элементов списка____________________________6
- Вставка элемента____________________________________7
- Удаление элемента из списка__________________________9
- Перестановка элементов списка_______________________10
- Копирование части списка____________________________11
- Слияние списков______________________________________12
6. Применение линейных списков_______________________________13
7. Мультисписки______________________________________________17
8. Нелинейные разветвленные списки___________________________18
9. Операции обработки списков_________________________________22
10. Заключение_________________________________________________29
11.Список Литературы___________________________________________30
Введение
Статическими величинами называются такие, память под которые выделяется во время компиляции и сохраняется в течение всей работы программы. В языках программирования (Pascal, C, др.) существует и другой способ выделения памяти под данные, который называется динамическим. В этом случае память под величины отводится во время выполнения программы. Такие величины будем называть динамическими. Раздел оперативной памяти, распределяемый статически, называется статической памятью; динамически распределяемый раздел памяти называется динамической памятью (динамически распределяемой памятью). Использование динамических величин предоставляет программисту ряд дополнительных возможностей. Во-первых, подключение динамической памяти позволяет увеличить объем обрабатываемых данных. Во-вторых, если потребность в каких-то данных отпала до окончания программы, то занятую ими память можно освободить для другой информации. В-третьих, использование динамической памяти позволяет создавать структуры данных переменного размера. Работа с динамическими величинами связана с использованием еще одного типа данных — ссылочного типа. Величины, имеющие ссылочный тип, называют указателями. Указатель содержит адрес поля в динамической памяти, хранящего величину определенного типа. Сам указатель располагается в статической памяти. Благодаря многим преимуществам, которые дает использование динамических структур, такой способ хранения данных повсеместно используется в программировании. Данная тема является особенно актуальной, поскольку в настоящее время невозможно написание функциональных программ без использования динамических структур. Для построения программ, с оптимизированным использованием памяти, необходимо уметь легко оперировать с динамическими структурами и использовать правильный подход к выбору метода решения задачи. Всё это говорит о том, что изучение этой темы является необходимостью. Целью данной работы является изучение динамических структур данных на конкретном примере связных списков, научиться оперировать с типами данных, использующими динамическую память.
Поставлена задача: Написать программы-примеры, реализующие основные алгоритмы работы со списками, приобрести опыт создания таких программ при отладке.
Связные линейные списки
Списком называется упорядоченное множество, состоящее из переменного числа элементов, к которым применимы операции включения, исключения. Список, отражающий отношения соседства между элементами, называется линейным. Если ограничения на длину списка не допускаются, то список представляется в памяти в виде связной структуры. Линейные связные списки являются простейшими динамическими структурами данных.
Графически связи в списках удобно изображать с помощью стрелок. Если компонента не связана ни с какой другой, то в поле указателя записывают значение, не указывающее ни на какой элемент. Такая ссылка обозначается специальным именем - nil.
Машинное представление связных линейных списков
На рисунке приведена структура односвязного списка. На нем поле INF - информационное поле, данные, NEXT - указатель на следующий элемент списка. Каждый список должен иметь особый элемент, называемый указателем начала списка или головой списка, который обычно по формату отличен от остальных элементов. В поле указателя последнего элемента списка находится специальный признак nil, свидетельствующий о конце списка.
Однако, обработка односвязного списка не всегда удобна, так как отсутствует возможность продвижения в противоположную сторону. Такую возможность обеспечивает двухсвязный список, каждый элемент которого содержит два указателя: на следующий и предыдущий элементы списка. Структура линейного двухсвязного списка приведена на рисунке где поле NEXT - указатель на следующий элемент, поле PREV - указатель на предыдущий элемент. В крайних элементах соответствующие указатели должны содержать nil, как и показано на рисунке.
Для удобства обработки списка добавляют еще один особый элемент - указатель конца списка. Наличие двух указателей в каждом элементе усложняет список и приводит к дополнительным затратам памяти, но в то же время обеспечивает более эффективное выполнение некоторых операций над списком.
Структура двухсвязного списка
Разновидностью рассмотренных видов линейных списков является кольцевой список, который может быть организован на основе как односвязного, так и двухсвязного списков. При этом в односвязном списке указатель последнего элемента должен указывать на первый элемент; в двухсвязном списке в первом и последнем элементах соответствующие указатели переопределяются, как показано на рисунке
При работе с такими списками несколько упрощаются некоторые процедуры, выполняемые над списком. Однако, при просмотре такого списка следует принятие некоторых мер предосторожности, чтобы не попасть в бесконечный цикл.
В памяти список представляет собой совокупность дескриптора и одинаковых по размеру и формату записей, размещенных произвольно в некоторой области памяти и связанных друг с другом в линейно упорядоченную цепочку с помощью указателей. Запись содержит информационные поля и поля указателей на соседние элементы списка, причем некоторыми полями информационной части могут быть указатели на блоки памяти с дополнительной информацией, относящейся к элементу списка. Дескриптор списка реализуется в виде особой записи и содержит такую информацию о списке, как адрес начала списка, код структуры, имя списка, текущее число элементов в списке, описание элемента и т.д., и т.п. Дескриптор может находиться в той же области памяти, в которой располагаются элементы списка, или для него выделяется какое-нибудь другое место.
Реализация операций над связными линейными списками
Во всех операциях чрезвычайно важна последовательность коррекции указателей, которая обеспечивает корректное изменение списка, не затрагивающее другие элементы. При неправильном порядке коррекции легко потерять часть списка.
В программных примерах подразумеваются определенными следующие типы данных:
любая структура информационной части списка: type data = ...;
элемент односвязного списка (sll - single linked list):
type
sllptr = ^slltype; { указатель в односвязном списке }
slltype = record { элемент односвязного списка }
inf : data; { информационная часть }
next : sllptr; { указатель на следующий элемент }
end;
элемент двухсвязного списка (dll - double linked list):
type
dllptr = ^dlltype; { указатель в двухсвязном списке }
dlltype = record { элемент односвязного списка }
inf : data; { информационная часть }
next : sllptr; { указатель на следующий элемент (вперед) }
prev : sllptr; { указатель на предыдущий элемент (назад) }
end;
Перебор элементов списка.
Эта операция, возможно, чаще других выполняется над линейными списками. При ее выполнении осуществляется последовательный доступ к элементам списка - ко всем до конца списка или до нахождения искомого элемента.
Алгоритм перебора для односвязного списка представляется программным примером
{==== Программный пример ====}
{ Перебор 1-связного списка }
Procedure LookSll(head : sllptr);
{ head - указатель на начало списка }
var cur : sllptr; { адрес текущего элемента }
begin
cur:=head; { 1-й элемент списка назначается текущим }
while cur <> nil do begin
< обработка c^.inf >
{обрабатывается информационная часть того эл-та,
на который указывает cur.
Обработка может состоять в:
печати содержимого инф.части;
модификации полей инф.части;
сравнения полей инф.части с образцом при поиске по ключу;
подсчете итераций цикла при поиске по номеру;
cur:=cur^.next;
{ из текущего эл-та выбирается указатель на следующий эл-т и для следующей итерации следующий эл-т становится текущим; если текущий эл-т был последний, то его поле next содержит пустой указатель и, т.обр. в cur запишется nil, что приведет к выходу из цикла при проверке условия while } end; end;