- •Адреси та вказівники
- •Вільна пам'ять
- •Динамічні масиви
- •Поняття динамічного лінійного списку
- •If not (s належить sqs) then
- •V : string;
- •Створення та обробка списку
- •Var p : pElem; begin
- •Var f:text; {вхідний текст}
- •If not isIn(s,h) {якщо рядка в списку немає}
- •Var sqs:pElem; {вказівник на голову списку}
- •Вилучення елемента списку
- •Var p:pElem; {допоміжний вказівник}
- •Var p:pElem; {допоміжний вказівник}
Створення та обробка списку
Реалізуємо дії в алгоритмі розв'язання задачі, сформульованої у попередньому параграфі. Подамо послідовність sqs лінійним зв'язаним списком рядків, на голову якого встановимо вказівник sqs типу PElem.
Створення порожнього списку. Дія sqs: =<> уточнюється як sqs:=nil.
Додавання елемента на початку списку
Найпростіший спосіб — додати елемент на початку списку. Для цього треба отримати ділянку вільної пам'яті під новий елемент списку, отримати ділянку під рядок, установити вказівник
в елементі списку на нього, записати в нього новий рядок, «прив'язати» старий головний елемент до нового й зробити новий головним.
Опишемо ці дії у такій процедурі (add — додати).
procedure add(s:string; var h:PElem);
Var p : pElem; begin
new(p); {отримати ділянку для елемента списку} new(р^.pval); {отримати ділянку для рядка} p^.pval^:=s; {записати в неї рядок}
{«прив'язати» стару голову до нового елемента} p^.next:=h; h: =р {та зробити його головним}
end;
Вказівник змінюється, тому він є параметром-змінною.
Визначення, чи належить рядок послідовності
Будемо рухатися елементами списку від його початку допоки не натрапимо на елемент, який вказує на рядок s, або не дійдемо до останнього елемента. Якщо натрапимо на елемент, що вказує на s, відповідь «так», інакше — «ні». Якщо послідовність порожня, то відповідь «ні».
Уточнимо ці дії. Нехай h указує на поточний елемент списку. Припустимо, що значення поля pval кожного елемента списку не дорівнює nil, тобто поле вказує на рядок.
Умову переходу до наступного елемента у пошуках s запишемо так.
(h^.next< >nil) and (h^.pval^ < >s) {рухатися можна і рухатися треба}
Перехід до наступного елемента задає оператор h: =h^. next. function isIn(s:string; h:PElem):boolean;
begin
if h=nil then isln:=false else begin
while (h^.next< >nil) and (h^.pval^ < >s) do
h:=h^.next;
{(h^.next=nil) or (h^.pval^=s)}
isIn:=(h^.pval^=s}
end
end;
Вказівник h на голову списку використовується для руху списком, тому його оголошено як параметр-значения, щоб змінювалася тільки його копія в локальній пам'яті. Список у нашій задачі представлено вказівником на голову sqs, і виклик функції матиме вигляд isIn (s, sqs).
Створення списку
Читання рядків з тексту та додавання елементів до списку реалізуємо процедурою, яка використовує наведені вище підпрограми (зовнішнє ім'я вхідного тексту не уточнюється)
procedure createList(var h:PElem);
Var f:text; {вхідний текст}
s:string;
begin
assign(f, '...');
reset(f);
h:=nil;
while not eof(f) do begin readln(f,s);
If not isIn(s,h) {якщо рядка в списку немає}
then add(s,h) {то додати його до списку}
end;
close(f);
end;
• При додаванні елементів на початку списку їх порядок у списку є зворотним до порядку їх надходження, тобто “останнім прийшов — перший у списку”.
Виведення рядків списку
Рядки в списку друкуються від його початку під час руху елементами.
procedure writeList(h:Pelem);
begin
while h< >nil do
begin writeln(h^.pval6); h:=h^.next
end
end;
Вказівник, що задає список, оголошено як параметр-значения, тому допоміжний вказівник для проходу списком не потрібний.
Програма розв'язання задачі
Зберемо оголошення типів Pstring, PElem, Elem та наведені вище підпрограми в модуль uLString і використаємо його в такій програмі.
program strListl;
uses uLString;