Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Struktura_danikh_Ch1

.pdf
Скачиваний:
6
Добавлен:
24.02.2016
Размер:
573.72 Кб
Скачать

3.5.1 Список з поточним елементом

Список з поточним елементом краще використовує динамічну пам’ять, ніж класичний список, завдяки іншому набору команд. Список з поточним елементом визначається як:

1Порожній список.

2Список; поточний елемент; список.

3Список.

Набір дій над списками з поточним елементом:

1Почати роботу.

2Чи порожній залишок списку?

3Перейти до початку списку.

4Перейти до наступного елемента.

5Поточний елемент.

6Вставити елемент.

7Видалити елемент.

Дії 1, 3, 4, 6, 7 – інструкції; 2 – відношення; 5 - операція. Інструкція “Почати роботу” повертає порожній список.

Відношення “Чи порожній залишок списку?” перевіряє, чи є елементи у списку, починаючи від поточного.

“Перейти до початку списку” – зробити поточним перший елемент списку.

“Перейти до наступного елемента” – зробити поточним наступний елемент списку. Якщо залишок списку порожній, то нічого робити не потрібно.

“Поточний елемент” повертає значення поточного елемента. Список при цьому не змінюється. Якщо залишок списку порожній, ця операція повинна давати відмову.

“Вставити елемент” – вставити новий елемент у список перед поточним. “Видалити елемент” – видалити поточний елемент. Поточним стає

наступний елемент. Якщо залишок списку порожній, інструкція повинна давати відмову.

Можлива реалізація списку з поточним елементом з використанням вказівників зображена на рис. 3.14. Елементи списку – це записи з двох полів: поле даних та вказівник на наступний елемент. За допомогою вказівника елементи списку з’єднані у ланцюг. У останньому елементі вказівник на наступний елемент дорівнює nil. Сам список – це запис з двох вказівників: вказівник на початок списку та вказівник на поточний елемент. Якщо список порожній, то елементів немає, а обидва вказівники дорівнюють nil. Вважається, що коли залишок списку порожній, вказівник на поточний елемент вказує за останній елемент списку (його значення при цьому дорівнює nil). Це потрібно для того, щоб можна було вставити новий елемент у будь-яке місце списку.

43

Рисунок 3.14 - Реалізація списку з поточним елементом

Опис інтерфейсної частини модуля має вигляд.

unit ListCurrent;

 

 

interface

 

 

type lref = ^lelem;

{Вказівник на елемент списку}

lelem = record

{Елемент списку}

d: integer;

 

 

next: lref

 

 

end;

 

 

list = record

{Список}

beg, cur: lref

 

 

end;

 

 

procedure Init(var l: list);

{ Почати роботу }

function EmpEnd(l: list): boolean;

{ Чи порожній залишок списку?}

procedure First(var l: list);

 

{ Встати до початку списку }

procedure Next(var l: list);

 

{ Перейти до наступного елемента }

function Current(l: list): integer;

{ Поточний елемент }

procedure Insert(var l: list; n: integer);{ Вставити елемент }

procedure Delete(var l: list);

 

{ Видалити елемент }

implementation

 

 

.................

 

 

end.

 

 

Вставка елемента у список зображена на рис. 3.15. Необхідно розглянути 2 випадки: коли вказівник на поточний елемент вказує на початок списку (перший елемент списку) та у середину списку. Перший випадок зображено на рис. 3.15 а), б), а другий - на рис. 3.15 в), г). Для вставки та видалення елемента використовують допоміжну внутрішню функцію, яка повертає вказівник на попередній елемент списку (p1 на рис. 3.15 г).

Видалення елемента списку зображено на рис. 3.16. Якщо залишок списку порожній, то функція дає відмову. Інакше, як і для вставки елемента, розглядається два випадки: коли вказівник на поточний елемент вказує на початок списку (перший елемент списку) та у середину списку. Перший випадок зображено на рис. 3.16 а), б), а другий - на рис. 3.16 в), г).

44

3.5.2 Кільцевий список

Кільцевий список відрізняється від списку з поточним елементом тим, що для кільцевого списку не визначають перший та останній елемент. Усі елементи пов’язані у кільце та відомий лише порядок слідування. Кільцевий список визначається як:

1Порожній список.

2Список; поточний елемент; список. Набір дій над кільцевими списками:

1Почати роботу.

2Довжина списку.

3Перейти до наступного елемента.

4Поточний елемент.

5Вставити елемент.

6Видалити елемент.

Дії 1, 3, 5, 6 – інструкції; 2, 4 - операції.

Інструкція “Почати роботу” повертає порожній список.

Операція “ Довжина списку” повертає кількість елементів у списку. “Перейти до наступного елемента” – зробити поточним наступний

елемент списку. Якщо список порожній, то нічого робити не потрібно. “Поточний елемент” повертає значення поточного елемента. Список при

цьому не змінюється. Якщо список порожній, ця операція повинна давати відмову.

“Вставити елемент” – вставити новий елемент у список перед поточним. “Видалити елемент” – видалити поточний елемент. Поточним стає

наступний елемент або список стає порожнім. Якщо список порожній, інструкція повинна давати відмову.

45

Рисунок 3.15 - Вставка елемента у список

46

Рисунок 3.16 – Видалення елемента списку

Можлива реалізація кільцевого списку з використанням вказівників зображена на рис. 3.17. Елементи списку – це записи з двох полів: поле даних та вказівник на наступний елемент. За допомогою вказівника елементи списку з’єднані у кільце. Сам список – це вказівник на поточний елемент. Якщо список порожній, то елементів немає, а вказівник дорівнює nil.

47

Рисунок 3.17 - Реалізація кільцевого списку

Для кільцевого списку з поточним елементом реалізація мовою Паскаль наведена у модулі IntRList. Підпрограми Init, Next, Current нескладні і тому виносяться на самостійне вивчення. Функція Len обчислює довжину списку за допомогою додаткового вказівника p. Поступово проходяться всі елементи списку до того моменту, коли p знову дорівнюватиме r - вказівнику на поточний елемент.

unit IntRList;

 

interface

 

type

 

rlist = ^relem;

{Список}

relem = record

{Елемент списку}

d: integer;

 

next: rlist

 

end;

 

procedure Init(var r: rlist);

{ Почати роботу }

function Len(r: rlist): integer;

{ Довжина списку }

procedure Next(var r: rlist);

{ Перейти до наступного елемента }

function Current(r: rlist): integer; { Поточний елемент }

procedure Insert(var r: rlist; n: integer);{ Вставити елемент }

procedure Delete(var r: rlist);

{ Видалити елемент }

implementation

.................

function Len; var i: word; p: rlist;

begin

i:=0; p:=r; if p<>nil then repeat

p:=p^.next;

i:=i+1 until p=r; Len:=i end;

48

.................

procedure Insert; var p: rlist; begin

new(p);

if r=nil then begin

p^.d:=n; p^.next:=p; end

else begin

p^:=r^; r^.d:=n; r^.next:=p; end;

r:=p;

end;

procedure Delete; var p: rlist; begin

if r=nil then begin

writeln('Delete: Список порожній'); halt

end;

if r^.next=r then begin

p:=r; r:=nil end

else begin

p:=r^.next; r^:=p^ end;

dispose(p)

end;

end.

На рис. 3.18 розглянуті два випадки вставки елемента у список: коли список порожній та непорожній. Перший випадок зображено на рис 3.18 а), б), а другий - на рис 3.18 в), г). Якщо список не порожній, то для вставки елемента у нього виконується така дія - у динамічній пам’яті вставляється елемент не перед, а після поточного. Це дає змогу не проходити весь список для зв’язування елементів у ньому (як це було, наприклад, у списках з поточним елементом). Після виділення пам’яті під новий елемент переносяться дані, які були у поточному елементі, у новий елемент (рис. 3.18 в).

49

Рисунок 3.18 - Вставка елемента у список

Дані нового елемента натомість заносяться у той елемент, який був поточним у списку. Після чого, поточний елемент пов’язується з новим, а вказівник пересувається на поточний елемент, щоб він вказував на новий елемент (рис. 3.18 г). З точки зору кільцевого списку, таким чином відбувається вставка елемента перед поточним.

Видалення елемента списку зображено на рис. 3.19. Якщо список порожній (r=nil), то процедура Delete дає відмову. Інакше, як і для вставки елемента, існує два випадки: коли список складається з одного елемента, та більше, ніж з одного елемента. Перший випадок зображено на рис. 3.19 а), б), а другий - на рис. 3.19 в), г). У другому випадку виконується алгоритм аналогічний вставці елемента. Тобто, видаляється не поточний, а наступний елемент, дані з якого спочатку переносяться у поточний елемент.

50

Рисунок 3.19 - Видалення елемента списку

Кільцеві списки можна використати для розв’язання такої задачі: вводиться послідовність натуральних чисел, треба впорядкувати її та показати результат. Підпрограма PutToList, вставляє число на своє місце у впорядкованій послідовності. Вважається, що поточний елемент кільцевого списку є найменшим, а далі елементи йдуть у порядку зростання. Процедура WriteList показує кільцевий список, починаючи з поточного елемента. Основна програма вводить послідовність та показує результат впорядкування.

Program TstRList; uses IntRList;

procedure PutToList(var r: rlist; n: integer); var l,i,j: word;

b: boolean; begin l:=Len(r); i:=0; b:=false;

while (i<l) and not b do begin b:=n<Current(r);

51

if not b then begin Next(r); i:=i+1;

end end;

Insert(r,n);

for j:=i+1 to l do Next(r);

end;

procedure WriteList(r: rlist); var i: word;

begin

for i:=1 to Len(r) do begin write(Current(r),' '); Next(r)

end;

writeln;

end;

var r: rlist; i: word; n: integer;

begin

Init(r);

writeln('Введіть послідовність до першого від”ємного числа'); readln(n);

while n>0 do begin PutToList(r,n); readln(n)

end;

writeln('Впорядкована послідовність'); WriteList(r)

end.

3.5.3 Двопов’язаний список

Двопов’язаний список схожий на список з поточним елементом. Але, на відміну від останнього, двопов’язаний список дозволяє однаково легко переходити як до наступного, так і до попереднього елемента списку.

Двопов’язаний список визначається як:

1Порожній список.

2Список; поточний елемент; список. Набір дій над двопов’язаними списками:

1Почати роботу.

52

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]