49679 (Динамические структуры данных)

2016-07-28СтудИзба

Описание файла

Документ из архива "Динамические структуры данных", который расположен в категории "". Всё это находится в предмете "информатика" из 1 семестр, которые можно найти в файловом архиве . Не смотря на прямую связь этого архива с , его также можно найти и в других разделах. Архив можно найти в разделе "лабораторные работы", в предмете "информатика, программирование" в общих файлах.

Онлайн просмотр документа "49679"

Текст из документа "49679"

Міністерство освіти і науки України

Національний технічний університет України «КПІ»

Кафедра медичної кібернетики та телемедицини

Лабораторна робота №1

Тема: Динамічні структури данних

Варіант №16 (задачі № 16.13(а), 16.18(а), 16.33).

Виконав:

студент ІМ-81

Плахтій Артур Миколайович

Перевірив:

старший викладач

Зінченко Ніна Павлівна

Київ 2009

Теоретична частина

1. Динамические структуры данных

Ранее изучаемые типы данных относятся к так называемым статическим. Память под них выделяется во время компиляции, количество таких объектов не меняется во время выполнения программы. Однако существует ряд задач, где статические структуры неэффективны. В языке Паскаль имеются средства создания динамических структур данных, которые позволяют во время выполнения программы:

  • образовывать объекты;

  • выделять для них память;

  • уничтожать, когда в них исчезает необходимость.

Другое название динамической памяти – куча.

Для получения ясного представления о динамических переменных надо рассмотреть структуру памяти во время выполнения программы на языке Паскаль (см. рис.1).

Данные в динамической памяти размещают с использованием указателей. Указатель - это ссылка на определенную ячейку памяти, начиная с которой записывается значение переменной, поэтому данные такого типа называются еще и ссылочным типом данных.

Формат описания ссылочного типа данных:

Type = ^ ,

то есть указатель связан с некоторым типом данных. Такие указатели называются типизированными.

Пример описания переменных ссылочного типа:

Type

p1=^integer;

p2=^real;

Var

A,B,C:p1;

X,Y,Z:p2;

P:char;

Cсылочные переменные A, B, C указывают на динамические объекты целого типа, X,Y,Z - вещественного, P - символьного. Значением ссылочной переменной является адрес в динамически выделенной памяти, где хранится объект этого типа.

Рис. 1. Структура памяти во время выполнения программы

Для обращения к ссылочной переменной используют запись “ A^ ”, что означает: ”идти по адресу, хранящемуся в A”. Память под указатели отводится на этапе компиляции.

Однако в Турбо Паскале можно объявлять указатель и не связывать его с конкретным типом данных. Такой указатель называется нетипизированным. Для его объявления служит стандартный тип pointer. Структура и тип таких данных могут меняться во время выполнения программы.

При работе с указателями обязательны этапа два:

  1. объявление указателя;

  2. формирование динамических данных, память которых отводится во время выполнения программы.

Для работы с указателями используются следующие процедуры:

New(P) - процедура, которая создает в динамической памяти новую переменную. Р - указатель переменной того типа, который надо создать. Каждая отдельная процедура new может создать только одну динамическую переменную.

Dispose(P) - процедура, позволяющая вернуть в кучу участок памяти, занятый объектом с указателем Р.

Параметрами процедур new и dispose может быть только типизированный указатель. Для работы с нетипизированными указателями используются аналогичные процедуры:

GetMem(P,Size) - резервирование памяти;

FreeMem(P,Size) - освобождение памяти.

Здесь Р - нетипизированный указатель,Size - размер в байтах требуемой или освобождаемой части кучи ( до 65521 байт).

Над указателями могут быть определены операции проверки на равенство и присваивание (рис.2):

Рис. 2. Допустимое присваивание

Пример.

Var x,y:^integer;

Begin

new(x); {порождаем динамический объект целого типа}

x^:=13; {по адресу x заносим значение 13}

y:=x; {в у заносим значение того же адреса, что и х}

writeln(y^);

end.

Ссылочной переменной может быть присвоенной “пустое” значение адреса, обозначенное служебным словом nil, что означает, что ссылочная переменная не указывает ни на один динамический объект. Это присваивание можно делать до выполнения процедуры new. Значение nil - это два нулевых слова. Оно может быть присвоено указателю любого типа.

Динамически размещенные данные можно использовать в любом месте программы, например:

Var a, b, c = ^ real;

Begin a^:=sqr(b^)+c^-17;

Недопустимо писать a:=sqr(b^), так как указателю нельзя присвоить значение вещественного выражения.

2. Линейные списки. Стек, очередь

Указатели являются эффективным средством построения списковых структур, к которым относятся, в частности, линейные списки.

Линейный список - это множество, состоящее из переменного числа узлов X[1], X[2], ... , X[n].

Структурные свойства такого списка:

  1. Если n>0, то Х[1] является первым узлом;

  2. Если 1

  3. Х[n] является последним узлом.

Среди возможных списковых структур выделяют некоторые специальные списки.

Стек - это линейный список, в котором все включения и исключения (и обычно всякий доступ) делаются в одном конце списка

Наглядный пример стеков: стопка подносов в столовой, железнодорожный тупик. Стеки используются в работе алгоритмов, имеющих рекурсивный характер. Конец стека называется вершиной стека. Принцип работы стека - “последний пришел - первый вышел”. Внизу находится наименее доступный элемент. Часто говорят, что элемент опускается в стек.

Очередь - это линейный список, в один конец которого добавляются элементы, а с другого конца исключаются. Принцип работы очереди: ”первый пришел - первый вышел”.

3. Организация списков в динамической памяти

Для организации списков используются структуры типа запись, состоящие из двух частей: информационной, где собственно и находятся данные, и ссылочной, содержащей указатель на следующий элемент списка (рис.1). Cоздадим в динамической памяти структуру:

Рис. 1. Пример списковой структуры

где Di - данные. Чтобы получить доступ к данным, достаточно хранить в памяти адрес начала этого списка nach.

В языке Турбо Паскаль последовательно проводится принцип, согласно которому, идентификатор, перед его использованием, должен быть описан. Исключение сделано только для указателей, которые могут ссылаться на еще не объявленный тип данных. Для описания элементов структуры подобной изображенной на рис. 3 можно использовать следующий ссылочный тип:

Type element=^Ptr;

Ptr=record

d:integer;

link:element;

end;

Список в динамической памяти можно создавать в прямом или обратном порядке (относительно последовательности вводимых элементов).

Пример создания списка в обратном порядке (см. рис.2):

Рис. 2. Пример создания списка в обратном порядке

Var i,n,a:integer;

tek,nach:Ptr;

Begin

tek:=nil;

readln(n);

for i:=1 to n do

begin

readln(a);

new(nach);

nach^.d:=a;

nach^.link:=tek;{цепочка присоединяется к nach}

{*} tek:=nach;

end;

end;

Обратим внимание на вызов процедуры new(nach). В результате этого вызова в динамической памяти отводится место для переменной типа record, которая в нашем случае состоит из двух полей: для хранения целочисленного значения и значения указателя, т.е. адреса. Здесь важно представлять, что после того, как переменная nach (или какая другая) создана в динамической памяти, тем самым имеем ее адрес, который сам является именем переменной, т.е. nach. Если у нас имеется другая переменная того же типа, tek, то мы знаем также и ее адрес, это tek. Поэтому, если в адресную часть переменной nach занести адрес tek, тем самым мы свяжем элементы nach и tek: nach^.link:=tek.

Алгоритм создания списка в прямом направлении:

1. Создать первый элемент nach.

Ввести nach^.d; pred:=nach;

2. Создать текущий элемент tek.

Ввести tek^.d;

Установить связь предыдущего с текущим: pred^.link:=tek;

текущий элемент становится предыдущим: pred:=tek;

3. Если не конец списка, то перейти на 2.

Обнулить адресную часть последнего элемента: tek^.link:=nil.

Рис. 3. Пример создания списка в прямом направлении

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

Просмотреть элементы списка можно следующим образом:

tek:=nach;{Встали на начало списка}

while tek<>nil do

begin

wtiteln(tek^.d);{Вывести информационную часть}

tek:=tek^.link; {Шаг по связи}

end;

Рассмотрим еще раз строку tek:=tek^.link; . Ее можно интерпретировать по-другому: значению адреса tek присвоить то, что хранится в адресной части элемента tek, а там хранится адрес элемента, следующего за tek. Вообще нотацию tek^.link следует различать в контексте ее нахождения: если она стоит слева от присваивания, имеется ввиду сама адресная часть элемента tek, а если справа от присваивания – то, что хранится в адресной части tek. Таким образом, например, tek^.link:=tek^.link будет означать: в адресную часть tek занести адрес элемента, следующего за tek.

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

Алгоритм добавления элемента в начало списка:

1. Создать новый элемент nov.

Ввести информационную часть nov^.d.

2. Построить связь: nov^.link:=nach.

3. Новый элемент сделать начальным: nach=nov.

Рис. 4. Добавление элемента в начало списка

Нетрудно удалить первый элемент (nach:=nach^.link). Главное - не забыть физически удалить его из памяти (процедура Dispose).

Добавление элемента в середину списка: пусть переменная tek указывает на элемент, после которого необходимо вставить в список элемент nov. Сначала нужно заполнить связь у элемента nov: nov^.link:=tek^.link; затем соединить tek и nov: tek^.link:=nov.

Рис. 5. Добавление элемента в середину списка

Добавление элемента в конец списка (рис.6). Пусть переменная pos указывает на последний элемент списка, nov – добавляемый элемент. Тогда операция pos^.link:=nov соединяет элементы; присваивание nov^.link:=nil обнуляет адресную часть нового элемента.

Рис. 6. Добавление элемента в конец списка

Удаление элемента из середины списка. Пусть переменная pred - элемент, предшествующий удаляемому элементу. Необходимо идти по ссылке, хранящейся в pred в поле link (адрес удаляемого элемента), затем идти по ссылке link удаляемого элемента (а это адрес следующего за удаляемым). Полученное значение записать в поле link элемента pred: pred^.link:=pred^.link^.link.

Рис. 7. Удаление элемента из списка

Исключение последнего элемента. Пусть pos - последний элемент, pred– предыдущий перед последним. Тогда присваивание pred^.link:=nil исключит последний элемент из цепи (рис. 8).

Рис. 8. Исключение последнего элемента из списка

Умова задачі

16.13. Одно из возможных представлений «длинного» текста —это разделить его на участки (строки) равной длины и создать массив ссылок на эти строки:

const d=…; {длина строки}

n=...; {максим, число строк}

type строка = array [l..d] of char,

ссылка =^строка;

текст = array [l..n] of ссылка;

(Если в тексте менее п строк, то последние элементы массива равны nil; в начале массива ссылок nil не должно быть. Если, в операции над текстом указан номер отсутствующей строки, т. е. элемент массива с этий номером равен nil, то такая операция не выполняется.)

Используя данное представление текста, описать:

а) функцию числострок(Т) для подсчета числа строк в тексте Т;

Алгоритм

Текст програми

program fwg;

uses crt;

const d=4;

n=40;

type stroka=array [1..d] of char;

nodepoint=^stroka;

Mas=array [1..n] of nodepoint;

Var f:text;

procedure kilkist(var k2:integer);

var ch:char;

begin

assign(f,'c:\f.txt');

reset(f);

k2:=0;

while not eof(f) do begin

read(f,ch);

k2:=k2+1;

end;

close(f);

end;

Function Kil(var cur1:mas):integer;

var i:integer;

begin

i:=1;

while (cur1[i]<>nil) and (i<>n) do begin

i:=i+1;

end;

kil:=i-1;

end;

procedure chut(var cur1:mas);

var ch:char;i,j:integer;

begin

Assign(f,'c:\f.txt');

reset(f);

for i:=1 to n do

cur1[i]:=nil;

i:=1;

while (not eof(f)) and (i

new(cur1[i]);

j:=1;

while (j

read(f,ch);

write(ch);

Cur1[i]^[j]:=ch;

j:=j+1;

end;

i:=i+1;

end;

close(f);

end;

procedure Vuvod(cur2:mas);

var i,j,k3:integer;

begin

i:=1;

kilkist(k3);

while cur2[i]<>nil do begin

writeln;

if (cur2[i+1]=nil) and (k3 mod 4<>0) then begin

for j:=1 to (k3 mod 4) do

write(cur2[i]^[j]);

end

else begin

for j:=1 to d do

write(cur2[i]^[j]);

end;

i:=i+1;

end;

end;

Var first:mas;q:integer;cha:char;

begin

ClrScr;

Chut(first);

readln;

Vuvod(first);

writeln;

readln;

q:=kil(first);

writeln('Kilkist strok:', q);

readln;

end.

Екран результату

Контрольні розрахунки

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

Умова задачі

Описать процедуру, которая вставляет:

а) в начало списка L новый элемент E;

Алгоритм розв’язку задачі

Текст програми

program Kill_Bill;

uses Crt;

type nodepoint=^node;

node=record

info:integer;

next:nodepoint;

end;

function Vvodsp(n1:integer):nodepoint;

var cur,firs:nodepoint;i:integer;

begin

if n1=0 then begin

Vvodsp:=nil;

end else

if n1=1 then begin

new(cur);

writeln('Vvedenya elementu spusku');

readln(cur^.info);

cur^.next:=nil;

Vvodsp:=cur;

end else

begin

new(cur);

write('Vvedenya elementu spusku: ');

readln(cur^.info);

cur^.next:=nil;

firs:=cur;

for i:=1 to n1-1 do begin

new(cur^.next);

write('Vvedenya elementu spusku: ');

readln(cur^.next^.info);

cur:=cur^.next;

cur^.next:=nil;

end;

Vvodsp:=firs;

end;

end;

procedure Vuvodsp(cur1:nodepoint);

begin

Writeln('Vuvedenya spusku');

while cur1<>nil do begin

writeln(cur1^.info);

cur1:=cur1^.next;

end;

end;

procedure Add_first(var cur:nodepoint;elem:integer);

var tm:nodepoint;

begin

new(tm);

tm^.info:=elem;

tm^.next:=cur;

cur:=tm;

end;

Procedure del(var cur2:nodepoint);

var cur:nodepoint;

begin

while cur2<>nil do begin

cur:=cur2^.next;

dispose(cur2);

cur2:=cur;

end;

end;

var n,E:integer;cur,L:nodepoint;

begin

ClrScr;

Write('Vedit kilkist elementiv spusku: ');

readln(n);

L:=Vvodsp(n);

writeln;

readln;

Vuvodsp(L);

writeln;

readln;

write('Enter the element which must be added to list: ');

readln(E);

Add_first(L,E);

Vuvodsp(L);

readln;

del(L);

end.

Екран результату

Умова задачі

16.33. Пусть L обозначает кольцевой (циклический) двунаправленный список с заглавным звеном (рис. 15) при следующем описании такого списка;

type ТЭ2=...; {тип элементов списка}

список2=^звено2;

звено2=гecord элем:ТЭ2;

пред,след:список2 end;

и пусть Е обозначает величину типа ТЭ2. Описать функцию или процедуру, которая:

г) определяет, есть ли в списке L хотя бы один элемент, который равен следующему за ним (по кругу) элементу;

ж) из списка L, содержащего не менее двух элементов, удаляет все элементы, у которых одинаковые «соседи» (первый и последний элементы считать соседями);

Алгоритм розв’язку задачі

Текст програми

program wqetg;

uses Crt;

type Nodepoint=^node;

node=record

count:integer;

next:nodepoint;

before:nodepoint;

end;

type nod=^nodepoint;

function Vvodsp(n:integer):nodepoint;

var j:integer;firs,cur1,cur:nodepoint;

begin

new(cur1);

writeln('Vedit Spisok');

cur1^.count:=0;

firs:=cur1;

cur1^.before:=nil;

cur1^.next:=nil;

for j:=1 to n do begin

new(cur1^.next);

cur1^.next^.before:=cur1;

cur1:=cur1^.next;

cur1^.next:=nil;

readln(cur1^.count);

end;

cur:=firs^.next;

cur1^.next:=cur;

cur^.before:=cur1;

Vvodsp:=firs;

end;

procedure Vuvodsp(head:nodepoint);

var cur:nodepoint;

begin

cur:=head^.next;

head:=head^.next;

writeln(head^.count);

head:=head^.next;

while head<>cur do begin

writeln(head^.count);

head:=head^.next;

end;

end;

function Kilkist(head:nodepoint;var cur:nodepoint):integer;

begin

if head=nil then Kilkist:=0

else if cur^.next=head then Kilkist:=1

else kilkist:=kilkist(head,cur^.next)+1;

end;

procedure DelEl(var cur:nodepoint);

var tm1,tm2:nodepoint;

begin

tm1:=cur^.before;

tm2:=cur^.next;

dispose(cur);

tm1^.next:=tm2;

tm2^.before:=tm1;

end;

procedure Del_Alike_n(var head:nodepoint);

var cur,cur2:nodepoint;b:boolean;

begin

b:=true;

cur:=head^.next;

cur2:=head^.next^.next;

while (b) do begin

b:=false;

while not(cur^.next=head^.next) do

begin

if cur^.count=cur2^.count then

begin

b:=true;

DelEl(cur2);

cur2:=cur^.next;

end

else

begin

cur:=cur^.next;

cur2:=cur2^.next;

end;

end;

end;

end;

var first,cur:nodepoint;m:integer;

begin

ClrScr;

writeln('Vedit kilkist elementiv spusku');

readln(m);

first:=Vvodsp(m);

writeln;

readln;

Vuvodsp(first);

Writeln;

readln;

Vuvodsp(first);

writeln;

readln;

cur:=first;

writeln(kilkist(first^.next,first^.next));

readln;

Del_Alike_n(first);

writeln('Spusok bez odnakovux susidiv: ');

Vuvodsp(first);

readln;

{del(first);}

end.

Екран результату

Висновок

Динамічні структури даних дозволяють гнучкіше та ширше використовувати можливості програмування. Дуже зручним у використанні є тип даних Паскаля Pointer та його комбінація з типом Record, що дає змогу реалізовувати списки та будь-які деревовидні структури даних. Середовище Турбо Паскаль та Делфі дозволяє вільно працювати з цими структурами.

Список літературних джерел

  1. Т. Рюттен, Г. Франкен. Турбо Паскаль 6.0. Торгово-издательськое бюро BHV. Грифон. - К.: 1992. - 235 с.

  2. Т. П. Караванова. Основи алгоритмізації та програмування. Форум. - К.: 2002. - 286 с.

  3. І.Скляр. Вивчаємо мову программування PASCAL. http://distance.edu.vn.ua/metodic/pascal/

  4. Будникова Н.А. Обучающий комплекс по программированию на языке ПАСКАЛЬ http://petrsu.ru/Chairs/IMO/pascal/

Свежие статьи
Популярно сейчас
Почему делать на заказ в разы дороже, чем купить готовую учебную работу на СтудИзбе? Наши учебные работы продаются каждый год, тогда как большинство заказов выполняются с нуля. Найдите подходящий учебный материал на СтудИзбе!
Ответы на популярные вопросы
Да! Наши авторы собирают и выкладывают те работы, которые сдаются в Вашем учебном заведении ежегодно и уже проверены преподавателями.
Да! У нас любой человек может выложить любую учебную работу и зарабатывать на её продажах! Но каждый учебный материал публикуется только после тщательной проверки администрацией.
Вернём деньги! А если быть более точными, то автору даётся немного времени на исправление, а если не исправит или выйдет время, то вернём деньги в полном объёме!
Да! На равне с готовыми студенческими работами у нас продаются услуги. Цены на услуги видны сразу, то есть Вам нужно только указать параметры и сразу можно оплачивать.
Отзывы студентов
Ставлю 10/10
Все нравится, очень удобный сайт, помогает в учебе. Кроме этого, можно заработать самому, выставляя готовые учебные материалы на продажу здесь. Рейтинги и отзывы на преподавателей очень помогают сориентироваться в начале нового семестра. Спасибо за такую функцию. Ставлю максимальную оценку.
Лучшая платформа для успешной сдачи сессии
Познакомился со СтудИзбой благодаря своему другу, очень нравится интерфейс, количество доступных файлов, цена, в общем, все прекрасно. Даже сам продаю какие-то свои работы.
Студизба ван лав ❤
Очень офигенный сайт для студентов. Много полезных учебных материалов. Пользуюсь студизбой с октября 2021 года. Серьёзных нареканий нет. Хотелось бы, что бы ввели подписочную модель и сделали материалы дешевле 300 рублей в рамках подписки бесплатными.
Отличный сайт
Лично меня всё устраивает - и покупка, и продажа; и цены, и возможность предпросмотра куска файла, и обилие бесплатных файлов (в подборках по авторам, читай, ВУЗам и факультетам). Есть определённые баги, но всё решаемо, да и администраторы реагируют в течение суток.
Маленький отзыв о большом помощнике!
Студизба спасает в те моменты, когда сроки горят, а работ накопилось достаточно. Довольно удобный сайт с простой навигацией и огромным количеством материалов.
Студ. Изба как крупнейший сборник работ для студентов
Тут дофига бывает всего полезного. Печально, что бывают предметы по которым даже одного бесплатного решения нет, но это скорее вопрос к студентам. В остальном всё здорово.
Спасательный островок
Если уже не успеваешь разобраться или застрял на каком-то задание поможет тебе быстро и недорого решить твою проблему.
Всё и так отлично
Всё очень удобно. Особенно круто, что есть система бонусов и можно выводить остатки денег. Очень много качественных бесплатных файлов.
Отзыв о системе "Студизба"
Отличная платформа для распространения работ, востребованных студентами. Хорошо налаженная и качественная работа сайта, огромная база заданий и аудитория.
Отличный помощник
Отличный сайт с кучей полезных файлов, позволяющий найти много методичек / учебников / отзывов о вузах и преподователях.
Отлично помогает студентам в любой момент для решения трудных и незамедлительных задач
Хотелось бы больше конкретной информации о преподавателях. А так в принципе хороший сайт, всегда им пользуюсь и ни разу не было желания прекратить. Хороший сайт для помощи студентам, удобный и приятный интерфейс. Из недостатков можно выделить только отсутствия небольшого количества файлов.
Спасибо за шикарный сайт
Великолепный сайт на котором студент за не большие деньги может найти помощь с дз, проектами курсовыми, лабораторными, а также узнать отзывы на преподавателей и бесплатно скачать пособия.
Популярные преподаватели
Добавляйте материалы
и зарабатывайте!
Продажи идут автоматически
5247
Авторов
на СтудИзбе
422
Средний доход
с одного платного файла
Обучение Подробнее