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

Struktura_danikh_Ch1

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

Рисунок 2.7 - Блок-схема алгоритму сортування методом вибору

23

2.3.3 Сортування даних методом включень

Приклад. Дано масив А= (3, 9, 5, 1, 8).

Необхідно обрати деякий елемент масиву X=аi та, порівнюючи його зі всіма попередніми, знайдемо його місце. Якщо всі попередні елементи вже були раніше упорядковані, то в результаті отримується упорядкована послідовність на одиницю більша за попередню.

Упорядкованості початкової послідовності можна досягти, починаючи описаний пpоцес з перших елементів масиву.

Наприклад, якщо розпочати з 2-го елемента X=а2=9 і порівняти його з попереднім елементом а1=3, то ці елементи залишаться на своїх місцях.

3-й елемент X=а3=5 порівнюється з попереднім а2=9 (а2>X=а3). Елемент а2 зсувається на місце а3. Елемент X ("старе” значення 5) порівнюється з наступним попереднім елементом а1=3 (а1<X). Елемент а1 залишається на тому ж місці. Отже, значення X надається елементу а2.

Масив набуває вигляд А= (3, 5, 9, 1, 8).

4-й елемент X=а4=1. Послідовно порівнюючи його з 3, 2 і 1-м елементами і послідовно зсуваючи їх в сторону а4, масив А приводиться до вигляду

А= (1, 3, 5, 9, 8).

Після виконання аналогічних дій з елементом X=а5=8 масив А набуде вигляду

А= (1,3, 5, 8, 9).

Алгоритм сортування, заснований на методі включення елемента в послідовність упорядкованих елементів, наведений на pис. 2.8.

24

Рисунок 2.8 - Блок-схема алгоритму сортування засобом включення

Питання для самоконтролю

1Дайте визначення масиву?

2Як обчислюється розмір пам’яті, необхідний для розміщення масиву даних?

3Як виконується зсув масиву даних?

4Які випадки необхідно розглядати під час зсуву елементів в кінець

масиву?

5Як виконується вставлення нового елемента в масив на заздалегідь відоме місце?

6Як виконується введення масиву з упорядкуванням його елементів?

7У чому полягає принцип сортування даних методом обміну?

8У чому полягає принцип сортування даних методом вибору?

9У чому полягає принцип сортування даних методом включень?

25

РОЗДІЛ 3 СПИСКИ

3.1 Класичний лінійний список

Лінійний список уявляє собою послідовність n ³ 0 вузлів Х[1], X[2], …, X[n], найважливішою структурною особливістю якої є таке розташування елементів списку один відносно іншого, начебто вони знаходяться на одній лінії. У такій структурі повинна виконуватися така умова: якщо n > 0 і X[1] є першим вузлом, а X[n] – останнім, то k-тий вузол X[k] йде за X[k-1] і передує вузлу X[k+1] для усіх 1 < k < n.

З лінійними списками можуть виконуватися наступні операції:

1Отримання доступу до k-го вузла списку для перевірки та/або зміни змісту його полів.

2Додавання нового вузла відразу після або до k-го вузла.

3Видалення k-го вузла.

4Об’єднання в одному списку двох (або більше) лінійних списків.

5Розбиття лінійного списку на два (або більше) списків.

6Створення копії лінійного списку.

7Визначення кількості вузлів в списку.

8Сортування вузлів у порядку зростання значень у визначених полях

цих вузлів.

9Пошук вузла з заданим значенням в деякому полі.

У операціях 1-3 дуже важливими є особливі випадки, коли k=1 та k=n, тому що доступ до першого та останнього елементів лінійного списку організувати набагато простіше, ніж до будь-якого іншого вузла списку.

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

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

2Перший елемент; список.

Над класичним списком можна виконувати такі дії:

1Почати роботу – повертає порожній список.

2Чи порожній список?

3Додати елемент – додати до списку один елемент, який стає першим у списку.

4Голова списку – повертає значення першого елемента. Список при цьому не змінюється. Для порожнього списку ця операція повинна давати відмову.

5Хвіст списку – повертає залишок списку без першого елемента. Хвіст порожнього списку за означенням – порожній список.

Дії 1, 3, 4, 5 – операції; 2 – відношення.

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

26

дорівнює nil. Сам список – це вказівник на початок. Якщо список порожній, то елементів немає, а вказівник дорівнює nil.

Рисунок 3.1 - Реалізація класичного списку

Модуль реалізації класичних списків наведено мовою Паскаль. Треба зазначити, що всі дії реалізовані за допомогою функцій. Функції Init, Empty, Head необхідно розглянути під час самостійної роботи. Функція Add (рис. 3.2) схожа на підпрограму вштовхування елемента у стек. Але, на відміну від останньої, Add повертає новий список, а не модифікує існуючий. Функція Tail повертає nil для порожнього списку або вказівник на другий елемент для непорожнього.

unit ListClassic;

 

 

interface

 

 

type list = ^lelem;

{Список}

lelem = record

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

d: integer;

 

 

next: list

 

 

end;

 

 

function Init: list;

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

function Empty(l: list): boolean;

{ Чи порожній список?}

function Add(l: list; n: integer): list;

{ Додати елемент }

function Head(l: list): integer;

 

{ Голова списку }

function Tail(l: list): list;

{ Хвіст списку }

implementation

 

 

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

 

 

function Add(l: list; n: integer): list; var p: list;

begin

new(p); p^.d:=n; p^.next:=l; Add:=p

end;

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

function Tail(l: list): list; begin

if l=nil then Tail:=nil else Tail:=l^.next

27

end;

end.

Рисунок 3.2 - Додавання елемента до списку

Під час оцінки розташування класичних списків у динамічній пам’яті необхідно звернути увагу на те, що функція Tail не вміщує жодного виклику dispose. Немає таких викликів і в інших функціях. Отже, одного разу виділена динамічна пам’ять ніколи не звільняється. Розташування списків у динамічній пам’яті зображене на рис. 3.3. З нього можна побачити, що декілька списків поділяють спільну пам’ять. Дійсно, після виконання ланцюга

l2:=Tail(l1); l2:=Add(l2,x); l2:=Add(l2,y)

списки l1 та l2 будуть мати спільні елементи (завершення списків). Оскільки пам’ять ніколи не звільняється, існує небезпека переповнення пам’яті. Якщо багато разів у циклі повторювати ланцюг l:=Add(l,x); l:=Tail(l), то, незважаючи на незмінний розмір списку l, можна отримати аварійне повідомлення про вичерпання динамічної пам’яті. Таким чином, хоч реалізація класичних списків дуже проста, вони використовують динамічну пам’ять неоптимально.

28

Рисунок 3.3 - Розміщення списків у динамічній пам’яті

Як приклад використання класичних списків можна навести задачу порівняння двох списків. Функція CmpLists перевіряє, чи співпадають два списки l1 та l2. Основна програма вводить 2 списки та показує результат порівняння.

Program ListClassTst; uses ListClassic;

function CmpLists(l1,l2: list): boolean; var b: boolean;

begin b:=true;

while not Empty(l1) and not Empty(l2) and b do begin

b:=Head(l1)=Head(l2); l1:=Tail(l1); l2:=Tail(l2) end;

CmpLists:=b and Empty(l1) and Empty(l2) end;

var l1,l2: list; i,n,m,k: word;

begin l1:=Init;

write('Кількість елементів 1-го списку: '); readln(n); for i:=1 to n do begin

write('l1(',i,')'); readln(k); l1:=Add(l1,k)

end;

l2:=Init;

write('Кількість елементів 2-го списку: '); readln(m); for i:=1 to m do begin

29

write('l2(',i,')'); readln(k); l2:=Add(l2,k)

end; write('Списки ');

if not CmpLists(l1,l2) then write('не '); writeln('співпадають')

end.

3.2 Стек

Стек – це лінійний список, в якому всі операції додавання та видалення (і, як правило, операції доступу до даних) виконуються тільки на одному з кінців списку.

Стек визначається як:

1Порожній стек.

2Верхівка стеку; стек.

Читати це означення треба так: стек – це або порожній стек, або вершина стеку, за яким йде стек.

Стек можна представити, як сукупність однотипних елементів, в якій є доступ тільки до верхнього елемента (рис. 3.4). Цей елемент називають вершиною стеку.

Рисунок 3.4 - Стек

Операції, відношення та інструкції для стеків:

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

2Чи порожній стек?

3Вштовхнути елемент у стек.

4Вершина стеку.

5Забрати вершину стеку.

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

“Вштовхнути елемент у стек” – додати до стеку один елемент, який стає верхівкою стеку.

30

“Верхівка стеку” – повернути верхній елемент. Стек при цьому не змінюється. Для порожнього стеку ця операція повинна давати відмову.

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

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

Рисунок 3.5 - Реалізація стеку

Як приклад можна навести модуль реалізації стеку символів.

{ Стек символів }

 

 

unit ChStack;

 

 

interface

 

 

type stack = ^selem;

{ Стек }

selem = record

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

d: char;

 

 

next: stack

 

 

end;

 

 

procedure Init(var s: stack);

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

function Empty (s: stack): boolean;

{ Чи порожній стек? }

procedure Push (var s: stack; c: char);

{ Вштовхнути елемент у стек }

function Top (s: stack): char;

{ Верхівка стеку }

procedure Pop (var s: stack);

{ Забрати верхівку стеку }

31

implementation

procedure Init(var s: stack); begin

s := nil end;

function Empty (s: stack): boolean; begin

Empty:= s=nil end;

procedure Push (var s: stack; c: char); var p: stack;

begin

new(p); p^.d := c; p^.next := s; s := p

end;

function Top (s: stack): char; begin

if s = nil then begin

writeln(' Top: Стек порожній'); halt end;

Top := s^.d end;

procedure Pop (var s: stack); var p: stack;

begin

if s = nil then begin

writeln(' Pop: Стек порожній'); halt end;

p:=s; s:= s^.next; dispose(p) end;

end.

В описах типів спочатку описується тип вказівника (stack),

type stack = ^selem;

а потім тип елемента стеку, на який вказує вказівник (selem).

selem = record d: char;

next: stack end;

32

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