ЛАБОРАТОРНАЯ РАБОТА №16 Тема: Разработка алгоритмов и программ с использованием динамических структур данных

Цель:Сформировать умения разрабатывать алгоритмы и программы с использованием динамических структур

Программное обеспечение: TURBO PASCAL 7.1

Оснащение:персональный компьютер, практикум

Время проведения: 2 уч. часа

Литература:

1. Немнюгин С.А. Turbo Pascal. Практикум. 2-е изд. СПб.: Питер, 2007. С. 138-149.

2. Павловская Т.А. Паскаль. Программирование на языке высокого уровня. Учебник для вузов. СПб.: Питер, 2008. С. 130-152.

ВОПРОСЫ ВХОДНОГО КОНТРОЛЯ:

1. Опишите операции с указателями.

2. Приведите примеры динамических переменных.

3. Пиведите пример динамических массивов.

КРАТКИЕ ТЕОРЕТИЧЕСКИЕ СВЕДЕНИЯ

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

Алгоритмы создания и работа с деревьями (добавление, удаление)

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

Type

Text = <тип запись>;

AdrT = ^Text;

AdrZv = ^Zveno;

Zveno = record

K1: <тип ключа>;

Lev, Prav: AdrZv;

Ard: ArdT;

End;

Var

DvDer: AdrZv;

МЕТОДИЧЕСКИЕ УКАЗАНИЯ

Принцип построения дерева

1. Первая запись делается корнем дерева.

2. Если ключ первой записи меньше ключа корня, то ей в соответствие ставится левая вершина, иначе – правая.

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

4. В зависимости от сравнения ключа К с ключом в очередной вершине, перемещаемся влево или вправо от нее до тех пор, пока не найдем подходящую вершину, к которой можно присоединить новую вершину с ключом К.

5. В зависимости от результата сравнения ключа вершины с ключом К делаем вновь сформированную вершину левой или правой для найденной вершины.

Включение нового элемента в дерево

Для включения записи в таблицу нужно найти в дереве вершину, к которой можно присоединить новый лист. Алгоритм поиска тождественен алгоритму поиска вершины с равным ключом. Нужная вершина найдена, если в качестве очередной ссылки, определяющей ветвь дальнейшего поиска, будет nil.

Пример.

(* считаем, что в дереве нет записи с тем же ключом *)

var

Zap: Text;

S: AdrZv;

T: AdrT;

Q, Root: AdrZv;

K: Integer;

Begin

New(T);

T^ := Zap;

New(S);

S^.K1 := K;

S^.AdrT := T;

S.Lev := nil;

L^.Prav := nil;

If Root = nil then Root := S

Else if K < Q^.K1 then Q^.Lev := S else Q^.Prav := S

Удаление записи из дерева

Если соответствующая вершина – лист дерева, или из нее выходит только одна ветвь, то для удаления записи достаточно скорректировать соответствующую ссылку вершины-предшественника. Если из удаляемой вершины выходит две ветви, то нужно найти подходящее звено дерева, которое можно было бы вставить на место удаляемого звена. Таким звеном является:

1. Самый правый элемент левого поддерева (выходящего из удаляемого элемента). Для достижения этого звена необходимо перейти в следующее от удаляемой вершины по левой ветви, а затем переходить в очередные вершины по правой ветви до тех пор, пока очередная ссылка вправо <> nil.

2. Самый левый элемент правого поддерева (выходящего из удаляемого элемента). Для достижения этого звена необходимо перейти в следующее от удаляемой вершины по правой ветви, а затем переходить в очередные вершины по левой ветви до тех пор, пока очередная ссылка вправо <> nil.

При исключении из дерева вершины с заданным ключом необходимо учесть три случая:

1. Звена с заданным ключом в дереве нет.

2. Звено с заданным ключом имеет не более одной ветви.

3. Звено с заданным ключом имеет две ветви.

Пример.

(* рекурсивная процедура исключения вершины с заданным ключом из дерева для варианта 1. Параметры: D – адрес корня дерева, K - ключ *)

procedure UDDer(Var D: AdrZv; K: Integer);

var Q: AdrZv;

procedure UD(Var R: AdrZv); { Рекурсивная процедура реализующая третий случай удаления; Начальное значение R – адрес левой вершины поддерева }

begin

if R^.Prav = nil then {Самая правая}

begin

Q^.K1 := R^.K1; {R – адрес замещающей вершины; Q – адрес замещаемой}

Q^.Adr := R^.Adr; {Ссылка на текст записи}

Q := R;

R := Q^.Lev; {Занесение в поле Prav звена-предшественника содержимого поля Lev из замещающего звена}

End

Else

UD(R^.Prav);

end;

begin

if D = nil then

Writeln(‘Звена нет’)

Else

If K < D^.Kl then

UDDer(D^.Lev, K)

Else

If K > D^.K1 then

UDDer(D^.Prav, K)

Else

Begin

Q := D; {В Q – адрес удаляемого звена}

If Q^.Prav = nil then

D := Q^.Lev {*} {Занесение ссылки на следующее звено}

Else

If Q^.Lev = nil then

D := Q^.Prav {**} {Занесение ссылки на следующее звено}

Else

UD(Q^.Lev); {***}

End;

end;

Для физического удаления удаляемого звена необходимо вместо (*) поставить

Begin

D := Q^.Lev;

Dispose(Q);

End

Аналогично на (**)

Для физического удаления замещающего звена вместо (***) нужно поставить

Dispose(Q);

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

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

type

Adr = ^Zveno;

Zveno = record

AdrSled: Adr;

Element: Char;

end;

Недостаток – движение возможно только в одном направлении.

Двунаправленные списки

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

type

Adr2 = ^Zveno2

Zveno2 = record

AdrSled: Adr2;

AdrPred: Adr2;

Element: <тип элемента списка>;

end;

СОДЕРЖАНИЕ РАБОТЫ: Написать алгоритм и отладить программу, используя условия задания лабораторной работы №15.

Вариант Задание
№1 ― по запросу выдаются сведения об автобусах, находящихся в парке.
№2 ― по запросу выдаются сведения об автобусах, находящихся в парке.
№3 ― по запросу выдаются сведения об автобусах, находящихся в парке.
№4 ― удаляет данные о списанных книгах.
№5 ― удаляет данные о списанных книгах.
№6 ― удаление заявок в список.
№7 ― удаление заявок.
№8 ― при выезде каждого автобуса из парка вводится номер автобуса, и программа удаляет данные об этом автобусе из списка автобусов, находящихся в парке.
№9 ― при выезде каждого автобуса из парка вводится номер автобуса, и программа удаляет данные об этом автобусе из списка автобусов, находящихся в парке.
№10 ― добавление данных о книгах, вновь поступающих в библиотеку.
№11 ― добавление данных о книгах, вновь поступающих в библиотеку.
№12 ― добавление заявок в список.
№13 ― добавление заявок.
№14 ― при въезде каждого автобуса в парк вводится номер автобуса, и программа записывает данные об этом автобусе в список автобусов, находящихся в парке.
№15 ― при въезде каждого автобуса в парк вводится номер автобуса, и программа записывает данные об этом автобусе в список автобусов, находящихся в парке.
№16 ― по запросу выдаются сведения о наличии книг в библиотеке.
№17 ― по запросу выдаются сведения о наличии книг в библиотеке.
№18 ― вывод всех заявок.

ВОПРОСЫ ВЫХОДНОГО КОНТРОЛЯ:

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

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

3. Дайте определение очереди и стека.

4. Приведите пример занесения элемента в стек.

5. Сформулируйте определение двоичного дерева.

ДОМАШНЕЕ ЗАДАНИЕ

Выучить определение дерева, стека, очереди. Приобрести навыки работы с динамическими структурами.

Наши рекомендации