Видалення елемента зі списку

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

Рис. 8.12. Видалення елемента зі списку

Оскільки вузол є динамічної змінної, то після виключення вузла зі списку він займає пам’ять повинна бути звільнена. Звільнення динамічної пам’яті, або, як іноді кажуть,”знищення змінної” виконується викликом процедури dispose. У процедури dispose один параметр – покажчик на динамічну змінну. пам’ять, займана цією динамічноїзмінної, повинна бути звільнена. наприклад, в програмі

var
р: ^ Integer;

begin
new (p);
{Інструкції програми} dispose (p);

end

створюється динамічна змінна р, а потім вона знищується. Звільнилася пам’ять зможуть використовувати інші змінні. Якщо цього не зробити, то, можливо, через нестачу вільної пам’яті в якийсь момент часу програма не зможе створити чергову динамічну змінну.
Наступна програма дозволяє додавати і видаляти вузли впорядкованого списку. Діалогове вікно програми наведено на рис. 8.13.
Процедури додавання вузла в список і виведення списку, а також оголошення типу вузла списку нічим не відрізняються від відповідних процедур рас смотреніі раніше програми Упорядкований динамічний список 2, тому вони тут не наводяться.
Видалення вузла зі списку виконує процедура TForm1.Button3Click, яка запускається натисканням кнопки Видалити (Buttons). Текст процедури приведений в лістингу 8.6.

Рис. 8.13. Вікно програми Динамічний список

Лістинг 8.6. Видалення вузла зі списку

unit dlist2 _;

interface

uses
Windows, Messages, SysUtils, Classes,

Graphics, Controls, Forms, Dialogs,
StdCtrls;

type
TForm1 = class (TForm)
Label1: TLabel;
Label2: TLabel;
Button1: TButton;
Button2: TButton;
Label3: TLabel;
Edit1: TEdit;
Edit2: TEdit;
procedure Button1Click (Sender: TObject);
procedure Button2Click (Sender: TObject);
procedure FormActivate (Sender: TObject);
private
{Private declarations}
public
{Public declarations}
end;

var
Form1: TForm1;

implementation
{$ R * .DFM}

type
TPStudent = ^ TStudent; // покажчик на тип TStudent

TStudent = record
f_name: string [20]; // прізвище
l_name: string [20]; // ім'я
next: TPStudent; // наступний елемент списку
end;

var
head: TPStudent; // початок (голова) списку

procedure TForm1.Button1Click (Sender: TObject);
var
node: TPStudent; // новий вузол списку
curr: TPStudent; // поточний вузол списку
pre: TPStudent; // попередній, щодо curr, вузол
begin
new (node); // створення нового елемента списку
node ^ .f_name: = Edit1.Text; // прізвище
node ^ .l_name: = Edit2.Text; // ім'я
// додавання вузла в список
// спочатку знайдемо підходяще місце в списку для вузла
curr: = head;
pre: = NIL;
{Увага!
якщо наведене нижче умова замінити
на (node.f_name > curr ^ .f_name) and (curr <> NIL)
то при додаванні першого вузла виникає помилка часу
виконання, так як curr = NIL і, отже,
змінної curr. ^ name немає!
У використовуваному варіанті умови помилка не виникає, так як
спочатку перевіряється умова (curr <> NIL), значення якого
FALSE і друга умова в цьому випадку не перевіряється.
}
while (curr<> NIL) and (node.f_name > curr ^ .f_name) do
begin
// введене значення більше поточного
pre: = curr;
curr: = curr ^ .next; // до наступного вузла
end;
if pre = NIL
then
begin
// новий вузол в початок списку
node ^ .next: = head;
head: = node;
end
else
begin
// новий вузол після pre, перед curr
node ^ .next: = pre ^ .next;
pre ^ .next: = node;
end;

Edit1.text: = '';
Edit2.text: = '';
Edit1.SetFocus;
end;

procedure TForm1.Button2Click (Sender: TObject);
var
curr: TPStudent; // поточний елемент списку
n: integer; // довжина (к-ть елементів) списку
st: string; // строкове представлення списку
begin
n: = 0;
st: = '';
curr: = head;
while curr <> NIL do
begin
n: = n + 1;
st: = st + curr ^ .f_name + '' + curr ^ .l_name + # 13;
curr: = curr ^ .next;
end;
if n <> 0
then ShowMessage ( 'Список:' + # 13 + st)
else ShowMessage ( 'У списку немає елементів.');
end;

procedure TForm1.FormActivate (Sender: TObject);
begin
head: = NIL;
end;

end.

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