2_Динамические структуры данных__линейные списки.ppt
- Количество слайдов: 37
Линейные списки
Списком называется структура данных, каждый элемент которой посредством указателя связывается со следующим элементом. Из определения следует: ¡ каждый элемент списка содержит поле данных (Data) (оно может иметь сложную структуру) ¡ Также каждый элемент списка содержит поле ссылки на следующий элемент (Next) ¡ поле ссылки последнего элемента должно содержать пустой указатель (NIL).
Nil u U^. Next ? ? ? U^. Data
Создание списка
Пример: Сформировать список, содержащий целые числа 3, 5, 1, 9. Решение Определим запись типа s с полями, содержащими характеристики данных — значения очередного элемента и адреса следующего за ним элемента. Type EXS =^S; S=Record Data: Integer; Next: EXS; End;
Получаем связанный однонаправленный список Nil u 3 5 1 9
Чтобы список существовал, надо определить указатель на его начало: Var u, x: EXS;
Создание первого элемента: New(u); {выделим место в памяти для переменной типа S} u^. next: =nil; {указатель пуст} u^. data: =3; {информационное поле первого элемента} Nil u U^. Next 3 U^. Data
Продолжим формирование списка. Для этого нужно добавить элемент в конец списка. х: =u; {введем вспомогательную переменную указательного типа, которая будет хранить адрес последнего элемента списка. Сейчас последний элемент списка совпадает с его началом} u Nil 3 x U^. Next U^. Data Т. е. , к области памяти можно обратиться через два указателя.
{выделим область памяти для следующего элемента cписка } New(x^. Next); u 3 x
{переменная х принимает значение адреса выделенной области памяти} x: =x^. Next; u 3 x
{определим значение этого элемента списка} x^. Data: =5; x^. Next: =Nil; Nil u 3 x 5
Procedure Init(Var u: Exs); {создание списка} Var x, у: Exs; Digit: Integer; {значение информационной части элемента Begin списка} Writeln(' Введите список '); u: = Nil; {список пуст} Write. Ln('Bвeдuтe элементы списка. Конец ввода 0’); Read( Digit); While Digit<>0 Do Begin New(y); {формирование элемента списка} y^. Next: =Nil; Y^. Data: =Digit; If u=nil Then u: =y {вставляем первый элемент списка} Else x^. Next: =y; {вставляем элемент в конец списка} x: =у; {переносим значение указателя на последний элемент Read(Digit); End; Writeln; End; списка}
Т. е. мы построили список добавлением элементов в конец списка. Nil u 3 5 1 9 Новая задача: вставить элемент в начало списка Nil u 7 3 5 1 9
{создание новой динамической переменной} New(x); Nil u 3 5 1 9 x
x^. data: =7; {информационное поле созданного элемента} x^. next: =u; {присоединим элементы списка u к созданному элементу} Nil u 3 5 1 9 x 7
u: =x; {изменим значение указателя начала списка} Nil u 3 5 1 9 x 7
Просмотр списка
Просмотр списка Просмотр элементов списка осуществляется последовательно, начиная с его начала. Указатель р последовательно ссылается на первый, второй и т. д. элементы списка до тех пор, пока весь список не будет пройден. При этом с каждым элементом списка выполняется операция Ор (некоторая Операция p). Начальное значение p - адрес первого элемента Whileсписка р^ не на конец списка} Do {p указывает Begin {выполнить с элементам р^ операцию Ор; перейти к следующему элементу} End;
Пусть Ор(р^) — это вывод элемента р^ на экран. Если р указывает на конец списка, то его значение равно NIL, то есть: While p<>Nil Do Begin Write(p^, ‘ ’); p: =р^. Next; End;
Пример: Сформировать список целых чисел упорядоченный по неубыванию. После ввода очередного числа с клавиатуры определяем его место в списке. При этом элемент может быть вставлен либо в начало списка, либо в конец его, либо во внутрь. Для того чтобы вставить в список элемент со значением Digit между двумя элементами, нужно найти элементы и запомнить их адреса (первый адрес — в переменной dx, второй — в рх), после чего установить новые связи с переменной, в которой хранится значение Digit.
Графически это можно представить так: dx px x Digit
Процедура Inshito, вставляющая в список элемент, переданный ей как параметр. Procedure Insinto(Digit: Integer; Var и: Exs); {вставка заданного элемента в список} Var dx, px, x: Exs; Begin New(x); x^. data: =Digit; x^. next: =NIL; {если список пуст, то вставляется первый элемент} If (u=Nil) Then u: =x Else {если список не пуст, то просматриваем его до тех пор, пока не отыщется подходящее место для х^ или не закончится список} Begin dx: =u; рх: =u; While (px<>Nil) And (px^. data<=Digit) Do Begin dx: =px; px: =px^. next; End; If px=Nil {пройден весь список} Then dx^. next: =x {элемент добавляется в конец списка} Else {пройден не весь список} Begin X^. next: =px; If px=u Then u: =x {вставляем в начало списка} Else dx^. next: =x; {вставляем внутрь списка} End;
Процедура Inshito, вставляющая в список элемент, переданный ей как параметр (продолжение) Begin {основная программа} u: =NIL; {список пуст} Writeln (‘ Введите элемент. Окончание ввода 0'); Read(Digit); While Digit<>0 Do Begin Insin. To(Digit, u); Read(Digit); End; Writeln ('cnucoк: '); Print(u); End.
Удаление элементов из списка
Пример: Удалить из заданного списка все вхождения элемента с заданным значением информационной части. . Обозначим u— исходный список, Digit — значение информационной части удаляемого элемента. Удалить элемент можно из любого места списка.
Удаление элемента из начала списка x u
Фрагмент программы х: =u; {запомним адрес первого элемента списка} u: =u^. next; {теперь u указывает на второй элемент списка} Dispose(x); {освободим память, занятую переменной x^)
Удаление элемента из середины списка dx u x
Фрагмент программы Нужно знать адреса удаляемого элемента и элемента, находящегося в списке перед ним. х: =u; {переменная х для хранения адреса удаляемого элемента} {найдем адреса нужных элементов списка } While (x<>Nil) And (x^. Data<>Digit) Do Begin dx: =x; х: =х^. Next End; Dx^. Next: =x^. Next; Dispose(x);
Удаление элемента из конца списка Производится, когда указатель dx показывает на предпоследний элемент списка, а х — на последний. {найдем предпоследний элемент} х: =u; dx: =u; While x^. Next<>NIL Do Begin dx: =x; x: =x^. Next; End; {удаляем элемент х^ из списка и освобождаем занимаемую им память} dx^. Next: = Nil; Dispose(x);
Процедура удаления элемента из списка Procedure Del(Digit: Integer; Var u: Exs); Var x, dx: Exs; Begin x: =u; While x<>Nil Do If x^. Data=digit Then Begin If x=u Then Begin u: =u^. Next; Dispose(x); х: =u End Else Begin dx ^. Next: =x^. Next; Dispose(x); x: =dx^. Next; End Else Begin dx: =x; x: =x^. Next; End;
Процедура удаления элемента из списка (продолжение) Procedure Del(Digit: Integer; Var u: Exs); Var x, dx: Exs; Begin x: =u; While x<>Nil Do If x^. Data=digit Then Begin If x=u Then Begin u: =u^. Next; Dispose(x);
Основная программа Begin Init(u); {формирование списка} Print(u ); {вывод списка} Write('Bведи число: '); Readln(Digit); Del(Digit, u); Print(u) End.
Задание 1 Прорисовать изменение значений переменной u при удалении из списка, изображенного на рисунке элементов со значением информационной части, равной 1 и 9. Nil u 3 5 1 9
Задание 2 N человек располагаются по кругу. Начав отсчет от первого, удаляют каждого k-го, смыкая при этом круг. Определить порядок удаления людей из круга. Для хранения данных об участниках игры используется список. u


