Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Курс 2_ Лекция_1_Ссылочные типы в ТП.doc
Скачиваний:
0
Добавлен:
01.04.2025
Размер:
86.53 Кб
Скачать

Пример 2.

P rogram ex2;

Var i:integer; p,q:^integer; {рис.1а}

Begin

New(p); new(q); i:=5; {рис.1б}

P^:=7; q^:=p^-i; i:=i+1; {рис.1в}

P^:=q^+i; q:=p; write(q^); {рис 1г}

End.

Место в памяти, ссылка на которое прежде являлась значением переменной q, теперь стало недоступным: нельзя, например, воспользоваться записанным там значением, нельзя освободить это место с помощью dispose, поскольку на него нет ссылки. Это место в памяти представляет так называемый «мусор». От него следовало бы избавиться до изменения значения переменной q. Заменим три последних оператора в программе ех2 на следующую группу операторов: P^:=q^+i; dispose(q);q:=p; write(q^); {рис 2a}

Предостережение. Если в ситуации, изображенной на рис.2а, выполнить dispose(p), то место в памяти, ссылка на которое была значением переменных p и q, освободится. После этого не только значение переменной р, но и значение переменной q будет неопределенным.

Стандартные процедуры new и dispose позволяют динамически порождать программные объекты и уничтожать их, что дает возможность использовать память компьютера более эффективно.

Пример 3.

Составить программу, которая в вещественном массиве с 1500 элементами находит элемент, номер которого равен наибольшему значению массива, состоящему из 3000 целых чисел.

Алгоритм решения.

  1. организуем динамический массив из целых чисел [1..3000]

  2. найдем в нем наибольший элемент к

  3. освободим память от этого массива и создадим динамический массив действительных чисел

  4. найдем элемент в этом массиве, номер которого равен к.

program ex3;

uses crt;

type ra=array[1..1500]of real;

ia=array[1..3000] of integer;

var k,i:integer;

p:^ra;q:^ia;

Begin

clrscr; randomize; k:=0;

new(q);

for i:=1 to 30 do

begin

q^[i]:=random(15)+6; write(q^[i]:4);

if q^[i]>k then k:=q^[i];

end;

writeln; writeln;

writeln('k= ',k);dispose(q);

new(p);

for i:=1 to 30 do

begin

p^[i]:=random(15)+random; write(p^[i]:5:1);

end;

writeln; writeln;

writeln('iskom element = ', p^[k]:4:1);

readkey;

End.

Однонаправленные списки и операции над ними

Главная возможность, которую предоставляет наличие ссылочных типов и ссылочных переменных в Паскале, - это возможность построения с их помощью объектов со сложной, меняющейся структурой, простейшим из которых является однонаправленный список.

Структура «однонаправленный список» строится подобно очереди на прием к врачу: клиенты сидят на любых свободных местах, но каждый из них знает, за кем он стоит (т.е. данные размещаются на свободных местах в памяти, но каждый элемент содержит ссылку на предыдущий или следующий элемент).

Однонаправленный список – это цепочка звеньев данных, где вместе с элементами указывается адрес следующего (или предыдущего) элемента.

Каждое звено списка обычно является записью, состоящей из двух частей:

  1. информационная часть (одно или несколько полей). Если р - ссылка на звено, то p^.имя поля1, p^.имя поля2, … - имена полей такого звена.

  2. Ссылочная часть содержит ссылку на следующее (или предыдущее) звено списка.

Описание списка.

При описании списка возникает проблема, что раньше описывать: звено, представляющее запись и содержащее поле-ссылку, или ссылку на звено? В Паскале принято сначала описывать ссылку на звено, например:

Type te=тип инф.части;

Ss=^zveno; {ссылка на звено}

Zveno=record {звено}

Inf: te; {информационная часть}

Sled:ss {ссылочная часть}

End;

Var p,u:ss;

Основные операции со списком.

1. Формирование списка

2. Вывод содержимого (просмотр элементов) списка на экран

  1. Удаление звена из списка

  2. Включение звена в список

  3. Поиск элемента в списке

Чтобы оперировать с элементами списка единообразно и просто, полезно ввести в употребление заглавное звено список. Информационную часть заглавного звена можно не использовать или использовать для побочных целей, например, для хранения величины – количества звеньев списка. Ссылочная часть заглавного звена содержит ссылку на первое звено списка, таким образом, у каждого звена списка будет “предыдущее” звено.

Пример 4. Процедура формирования списка натуральных чисел вводимых с клавиатуры.

Ввод числа 0 означает окончание формирования списка. Пусть u и p – имена ссылок на заглавный и текущий звенья списка.

Алгоритм:

Сначала выделяем место в памяти для заглавного звена New(u), текущая ссылка - р вначале указывает на заглавное звено;

Далее, если вводится число неравное нулю, то с помощью ссылки p^.sled формируется очередное звено списка, и текущий указатель р переводится на это звено

Procedure form;

var s:integer;

Begin

New(u); p:=u; u^.sled:=nil; Writeln(‘введите список натуральных чисел, окончание ввода - 0’);

Readln(s);

While s<>0 do

begin new (p^.sled);p:=p^.sled; p^.inf:=s; p^.sled:=nil;

readln(s);

end; writeln

End;

Пример 5. Процедура вывода элементов списка на экран

Алгоритм:

Текущую ссылку р связываем с первым звеном списка (u^.sled -имя указателя на первое звено);

Затем связываемся со вторым звеном, изменив значение р на значение p^.sled, и продолжаем цикл просмотра элементов списка, пока выполняется условие p<>nil. Если список был пустым (было выполнено отношение p=nil), то тело цикла не выполнится ни разу и не будет выведено ни одного числа.

Procedure print;

Var p:ss;

Begin p:=u^.sled;

While p<>nil do

begin write (p^.inf, ‘ ‘);

P:=p^.sled;

end; writeln;

End;

Пример 6. Процедура удаления звена из списка

Напишем процедуру, удаляющею звено из списка с помощью ссылки р на звено, за которым следует удаляемое звено.

Операция удаления звена из списка требует изменения лишь одной ссылки, что геометрически выглядит как изменение одной стрелки:

Список до удаления звена с элементом с