Добавил:
БГУИР ПОИТ Дистанционное Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ИПР2 / ИПР 2.docx
Скачиваний:
29
Добавлен:
06.10.2021
Размер:
700.75 Кб
Скачать

БЕЛОРУССКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ

ИНФОРМАТИКИ И РАДИОЭЛЕКТРОНИКИ

Кафедра программного обеспечения информационных технологий

Факультет КСиС

Специальность ПОИТ

Индивидуальная практическая работа №2

по дисциплине «Структуры и алгоритмы обработки данных»

Выполнил студент: Бордон Е.С.

группа 991051

Зачетная книжка № 99105004

Минск 2020

Задание №1:

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

Программа реализована на языке Delphi в программной среде Lazarus.

Процедура добавления вершин в дерево:

type

TData = Integer; //Тип ключа (тип основных данных) узла дерева.

TPNode = ^TNode; //Тип указателя на узел.

TNode = record //Тип узла дерева.

Data : TData; //Ключ (основные данные) узла дерева.

PLeft, PRight : TPNode; //Указатели на левый и правый узел.

end;

{Добавление узла с ключом aData в двоичное дерево поиска.}

procedure AddNode(var aPNode : TPNode; const aData : TData);

begin

if aPNode = nil then //Вставка узла.

begin

New(aPNode); //Выделяем память для узла.

aPNode^.Data := aData; //Записываем в узел значение ключа.

aPNode^.PLeft := nil; //Обнуление указателя на левого потомка.

aPNode^.PRight := nil; //Обнуление указателя на правого потомка.

end

else if aData <= aPNode^.Data then //Поиск места вставки в левом поддереве.

AddNode(aPNode^.PLeft, aData)

else if aData > aPNode^.Data then //Поиск места вставки в правом поддереве.

AddNode(aPNode^.PRight, aData);

Процедура поиска вершины:

procedure TForm2.find(const aPNode : TPNode; const aName : String);

begin

if aPNode <> nil then

begin

if edit2.text = inttostr(aPNode^.Data) then

rez:=aName;

find(aPNode^.PLeft, aName + '1'); //Рекурсивный вызов для левого поддерева.

find(aPNode^.PRight, aName + '2'); //Рекурсивный вызов для правого поддерева.

end;

end;

procedure TForm2.Button5Click(Sender: TObject); // Поиск

begin

if edit2.text = '' then begin

showmessage ('Ошибка! Введите значение');

exit;

end;

if FPTree = nil then begin

showmessage ('Дерево пустое!');

exit;

end;

rez:='';

find (FPTree,'0'); // Поиск

if rez = '' then

Memo1.Lines.Add('Вершина: ' + edit2.text + '; Не найдена!')

else

Memo1.Lines.Add('Вершина: ' + edit2.text + '; Адрес: ' + rez);

edit2.clear;

end;

Рис 1. Скриншоты работы программы Задание 1

Листинг всей программы приведен в конце работ.

Задание №2:

Ввести 10-15 целых чисел и построить из них АВЛ-дерево. Выполнить операцию поиска указанных элементов в АВЛ-дереве.

Программа реализована на языке Delphi в программной среде Lazarus.

Процедура добавления и перестановки вершин:

procedure Add(x : Integer; var p : TPNode; var h : boolean);

begin

if (p = nil)

then

begin

new(p);

h := true;

p^.Data := x;

p^.Pleft := nil;

p^.Pright := nil;

p^.depth := 0;

end

else

if (x < p^.Data) then begin

Add(x, p^.Pleft, h);

if h then

case p^.depth of

1: begin

p^.depth := 0;

h := false;

end;

0: p^.depth:=-1;

-1: begin

if (p^.Pleft^.depth = -1) then

PrightTurn(p)

else

PrightPleftTurn(p);

p^.depth := 0;

h := false;

end;

end;

end

else

if (x > p^.Data) then

begin

Add(x, p^.Pright, h);

if h then

case p^.depth of

-1: begin

p^.depth := 0;

h := false;

end ;

0: p^.depth:=1;

1: begin

if (p^.Pright^.depth = 1) then

PleftTurn(p)

else

PleftPrightTurn(p);

p^.depth := 0;

h:= false;

end;

end;

end

else

h := false;

end;

procedure PrightTurn(var p : TPNode);

var

tmp : TPNode;

begin

tmp := p^.Pleft;

p^.Pleft := tmp^.Pright;

tmp^.Pright := p;

p^.depth := 0;

p := tmp;

end;

procedure PleftTurn(var p : TPNode);

var

tmp : TPNode;

begin

tmp := p^.Pright;

p^.Pright := tmp^.Pleft;

tmp^.Pleft := p;

p^.depth := 0;

p := tmp;

end;

procedure PrightPleftTurn(var p : TPNode);

var

tmp : TPNode;

t : TPNode;

begin

tmp := p^.Pleft;

t := tmp^.Pright;

tmp^.Pright := t^.Pleft;

t^.Pleft := tmp;

p^.Pleft := t^.Pright;

t^.Pright := p;

if (t^.depth = -1) then

p^.depth := 1 else

p^.depth := 0;

if (t^.depth = 1) then

tmp^.depth := -1 else

tmp^.depth := 0;

p := t;

end;

procedure PleftPrightTurn(var p : TPNode);

var

tmp : TPNode;

t : TPNode;

begin

tmp := p^.Pright;

t := tmp^.Pleft;

tmp^.Pleft := t^.Pright;

t^.Pright := tmp;

p^.Pright := t^.Pleft;

t^.Pleft := p;

if (t^.depth = 1) then

p^.depth := -1 else

p^.depth := 0;

if (t^.depth = -1) then

tmp^.depth := 1 else

tmp^.depth := 0;

p := t;

end;

Листинг всей программы приведен в конце работы.

Рис 2. Скриншот работы программы задание 2

Задание №3:

Представить ориентированный граф, состоящий из 7-10 вершин, с помощью матрицы смежности. Указать вершину-источник, а затем решить следующие задачи.

1. Кратчайшие пути от вершины-источника до всех вершин орграфа на основе алгоритма Дейкстры.

2. Кратчайшие расстояния между каждой парой вершин орграфа на основе алгоритма Флойда.

Программа реализована на языке Delphi в программной среде Lazarus.

Основные процедуры, задействованные в программе:

procedure Floid(n : integer);

var

k,i,j:integer;

begin

for k:=0 to n - 1 do

for i:=0 to n - 1 do

for j:=0 to n - 1 do

g[i,j] := Min(g[i,j], g[i,k] + g[k,j]);

end;

procedure Dijkstra(s : longint; n : longint);

var

i, bliz, x :integer;

begin

setlength(dist,Length(dist)+n);

setlength(done,Length(done)+n);

for i:=0 to n - 1 do

begin

dist[i] := maxlongint;

done[i] := false;

end;

dist[s] := 0;

for i:=0 to n - 1 do

begin

bliz := -1;

for x:=0 to n - 1 do

if ((not done[x]) and ((bliz = -1) or (dist[x] < dist[bliz]))) then bliz := x;

if dist[bliz] = maxlongint then break;

done[bliz] := true;

for x:=0 to n - 1 do

if (g[bliz,x] <> maxlongint)

then begin

if (dist[bliz] + g[bliz,x] < dist[x]) then dist[x] := dist[bliz] + g[bliz,x];

end;

end;

end;

Листинг всей программы приведен в конце работы.

Рис 3. Скриншот работы программы.

Листинг программы Задание 1:

unit Unit2;

{$mode objfpc}{$H+}

Interface

uses

Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls, StdCtrls,

Menus;

type

//Тип ключа (тип основных данных) узла дерева.

TData = Integer;

//Тип указателя на узел.

TPNode = ^TNode;

//Тип узла дерева.

TNode = record

Data : TData; //Ключ (основные данные) узла дерева.

PLeft, PRight : TPNode; //Указатели на левый и правый узел.

end;

{ TForm2 }

TForm2 = class(TForm)

Button1: TButton;

Button2: TButton;

Button4: TButton;

Button5: TButton;

Button6: TButton;

Edit1: TEdit;

Edit2: TEdit;

Image1: TImage;

Label1: TLabel;

Label2: TLabel;

Label3: TLabel;

MainMenu1: TMainMenu;

Memo1: TMemo;

MenuItem1: TMenuItem;

MenuItem2: TMenuItem;

PaintBox1: TPaintBox;

procedure Button1Click(Sender: TObject);

procedure Button2Click(Sender: TObject);

procedure Button4Click(Sender: TObject);

procedure Button5Click(Sender: TObject);

procedure Button6Click(Sender: TObject);

procedure Edit1KeyPress(Sender: TObject; var Key: char);

procedure Edit2KeyPress(Sender: TObject; var Key: char);

procedure FormClose(Sender: TObject);

procedure Draw(aName : String);

procedure DrawText (aName, aPNode_date : String);

procedure MenuItem2Click(Sender: TObject);

procedure TreeFree(var aPNode : TPNode);

procedure AddNode(var aPNode : TPNode; const aData : TData);

procedure TreeWriteln(const aPNode : TPNode; const aName : String; aSL : TStrings);

procedure find(const aPNode : TPNode; const aName : String);

procedure Del_tree (var x : TPNode; y:integer);

private

public

FPTree : TPNode;

end;

var

Form2: TForm2;

rez:string;

Implementation

{$R *.lfm}

{ TForm2 }

//Процедура для освобождения памяти, занятой деревом. (Удаление дерева).

procedure TForm2.TreeFree(var aPNode : TPNode);

begin

if aPNode = nil then

Exit;

TreeFree(aPNode^.PLeft); //Рекурсивный вызов для освобождения памяти в левом поддереве.

TreeFree(aPNode^.PRight); //Рекурсивный вызов для освобождения памяти в правом поддереве.

Dispose(aPNode); //Освобождение памяти, занятой для текущего узла.

aPNode := nil; //Обнуление указателя на текущий узел.

end;

{Добавление узла с ключом aData в двоичное дерево поиска.}

procedure TForm2.AddNode(var aPNode : TPNode; const aData : TData);

begin

if aPNode = nil then //Вставка узла.

begin

New(aPNode); //Выделяем память для узла.

aPNode^.Data := aData; //Записываем в узел значение ключа.

aPNode^.PLeft := nil; //Обнуление указателя на левого потомка.

aPNode^.PRight := nil; //Обнуление указателя на правого потомка.

end

else if aData <= aPNode^.Data then //Поиск места вставки в левом поддереве.

AddNode(aPNode^.PLeft, aData)

else if aData > aPNode^.Data then //Поиск места вставки в правом поддереве.

AddNode(aPNode^.PRight, aData);

end;

procedure TForm2.TreeWriteln(const aPNode : TPNode; const aName : String; aSL : TStrings);

var

arrname: array of array of string;

i:integer;

begin

i:=0;

if aPNode <> nil then

begin

setlength(arrname,Length(arrname)+1,2);

arrname[i,0]:= aName;

arrname[i,1]:= IntToStr(aPNode^.Data);

inc(i);

aSL.Add(aName + ': ' + IntToStr(aPNode^.Data));

TreeWriteln(aPNode^.PLeft, aName + '1', aSL); //Рекурсивный вызов для левого поддерева.

TreeWriteln(aPNode^.PRight, aName + '2', aSL); //Рекурсивный вызов для правого поддерева.

end;

for i:=0 to Length(arrname)-1 do begin

Form2.Draw (arrname[i,0]);

Form2.DrawText (arrname[i,0], arrname[i,1]);

end;

arrname:=nil;

end;

procedure TForm2.Draw (aName : String); // Рисунок дерева

const

LevelHeight = 50;

var

s,s1:string;

i,x,y,dx:integer;

begin

PaintBox1.Canvas.Pen.Width:=3; // толщина линий

dx:= round(PaintBox1.Width / 5);

x:= round(PaintBox1.Width / 2);

y:=25;

s:='';

s1:='';

for i:=1 to length(aName) do begin

s:=copy(aName,i,1);

s1:=copy (aName,i-1,1);

if s='0' then begin

PaintBox1.Canvas.MoveTo(x,y);

end;

if s='1' then

begin

if s1='0' then

begin

x:= x-dx;

y:=y+LevelHeight;

dx:=round(dx/2);

PaintBox1.Canvas.lineTo(x,y) ;

PaintBox1.Canvas.Ellipse((x+(dx*2))-20,(y-LevelHeight)-20,(x+(dx*2))+20,(y-LevelHeight)+20);

PaintBox1.Canvas.Ellipse(x-20,y-20,x+20,y+20);

end;

if s1='1' then

begin

PaintBox1.Canvas.MoveTo(x,y);

x:= x-dx;

y:=y+LevelHeight;

dx:=round(dx/2);

PaintBox1.Canvas.lineTo(x,y);

PaintBox1.Canvas.Ellipse((x+(dx*2))-20,(y-LevelHeight)-20,(x+(dx*2))+20,(y-LevelHeight)+20);

PaintBox1.Canvas.Ellipse(x-20,y-20,x+20,y+20);

end;

if s1='2' then

begin

PaintBox1.Canvas.MoveTo(x,y);

x:= x-dx;

y:=y+LevelHeight;

dx:=round(dx/2);

PaintBox1.Canvas.lineTo(x,y);

PaintBox1.Canvas.Ellipse((x+(dx*2))-20,(y-LevelHeight)-20,(x+(dx*2))+20,(y-LevelHeight)+20);

PaintBox1.Canvas.Ellipse(x-20,y-20,x+20,y+20);

end;

end;

if s='2' then

begin

if s1='0' then

begin

x:= x+dx;

y:=y+LevelHeight;

dx:=round(dx/2);

PaintBox1.Canvas.lineTo(x,y) ;

PaintBox1.Canvas.Ellipse((x-(dx*2))-20,(y-LevelHeight)-20,(x-(dx*2))+20,(y-LevelHeight)+20);

PaintBox1.Canvas.Ellipse(x-20,y-20,x+20,y+20);

end;

if s1='1' then

begin

PaintBox1.Canvas.MoveTo(x,y);

x:= x+dx;

y:=y+LevelHeight;

dx:=round(dx/2);

PaintBox1.Canvas.lineTo(x,y);

PaintBox1.Canvas.Ellipse((x-(dx*2))-20,(y-LevelHeight)-20,(x-(dx*2))+20,(y-LevelHeight)+20);

PaintBox1.Canvas.Ellipse(x-20,y-20,x+20,y+20);

end;

if s1='2' then

begin

PaintBox1.Canvas.MoveTo(x,y);

x:= x+dx;

y:=y+LevelHeight;

dx:=round(dx/2);

PaintBox1.Canvas.lineTo(x,y);

PaintBox1.Canvas.Ellipse((x-(dx*2))-20,(y-LevelHeight)-20,(x-(dx*2))+20,(y-LevelHeight)+20);

PaintBox1.Canvas.Ellipse(x-20,y-20,x+20,y+20);

end;

end;

end;

end;

procedure TForm2.DrawText (aName, aPNode_date : String); // Рисунок TEXT на дереве

const

LevelHeight = 50;

var

s,s1:string;

i,x,y,dx:integer;

begin

PaintBox1.Canvas.Font.Size := 8;

PaintBox1.Canvas.Font.Name := 'courier';

dx:= round(PaintBox1.Width / 5);

x:= round(PaintBox1.Width / 2);

y:=25;

s:='';

s1:='';

if length(aName) = 1 then begin

PaintBox1.Canvas.Ellipse(x-20,y-20,x+20,y+20);

PaintBox1.Canvas.TextOut(x-5,y-5,aPNode_date);

end;

for i:=1 to length(aName) do begin

s:=copy(aName,i,1);

s1:=copy (aName,i-1,1);

if s='1' then

begin

if s1='0' then

begin

x:= x-dx;

y:=y+LevelHeight;

dx:=round(dx/2);

if i = length(aName) then

PaintBox1.Canvas.TextOut(x-5,y-5,aPNode_date);

end;

if s1='1' then

begin

x:= x-dx;

y:=y+LevelHeight;

dx:=round(dx/2);

if i = length(aName) then

PaintBox1.Canvas.TextOut(x-5,y-5,aPNode_date);

end;

if s1='2' then

begin

x:= x-dx;

y:=y+LevelHeight;

dx:=round(dx/2);

if i = length(aName) then

PaintBox1.Canvas.TextOut(x-5,y-5,aPNode_date);

end;

end;

if s='2' then

begin

if s1='0' then

begin

x:= x+dx;

y:=y+LevelHeight;

dx:=round(dx/2);

if i = length(aName) then

PaintBox1.Canvas.TextOut(x-5,y-5,aPNode_date);

end;

if s1='1' then

begin

x:= x+dx;

y:=y+LevelHeight;

dx:=round(dx/2);

if i = length(aName) then

PaintBox1.Canvas.TextOut(x-5,y-5,aPNode_date);

end;

if s1='2' then

begin

x:= x+dx;

y:=y+LevelHeight;

dx:=round(dx/2);

if i = length(aName) then

PaintBox1.Canvas.TextOut(x-5,y-5,aPNode_date);

end;

end;

end;

end;

procedure TForm2.MenuItem2Click(Sender: TObject); // Задание

begin

Showmessage(' Ввести 10-15 целых чисел и построить из них с помощью ука'+

'зателей бинарное дерево поиска. Обойти его прямым, симметричным и об'+

'ратным способами. Реализовать процедуры поиска, вставки и удаления эле'+

'ментов бинарного дерева поиска.');

end;

procedure TForm2.Button1Click(Sender: TObject); //Добавление узла в дерево.

var

Data : TData;

begin

if TryStrToInt(Edit1.Text, Data) then

begin

AddNode(FPTree, Data);

Label1.Caption := IntToStr(Data);

end

else

begin

Showmessage('Ошибка! Введите целое число');

Label1.Caption := 'Ошибка!';

end;

edit1.clear;

end;

procedure TForm2.Button2Click(Sender: TObject); //Распечатка дерева.

begin

Memo1.Lines.Add('-----');

Memo1.Lines.Add('Дерево:');

if FPTree = nil then

Memo1.Lines.Add('Дерево пустое.')

else

TreeWriteln(FPTree, '0', Memo1.Lines);

end;

procedure TForm2.Button4Click(Sender: TObject); // очистить дерево

begin

TreeFree(FPTree); //Освобождение памяти, занятой для элементов дерева (очистка дерева).

Memo1.clear;

Memo1.Lines.Add('Память, выделенная для дерева - освобождена.');

PaintBox1.Invalidate; // Очищает рисунок фон оставляет прозрачным

end;

procedure TForm2.find(const aPNode : TPNode; const aName : String);

begin

if aPNode <> nil then

begin

if edit2.text = inttostr(aPNode^.Data) then

rez:=aName;

find(aPNode^.PLeft, aName + '1'); //Рекурсивный вызов для левого поддерева.

find(aPNode^.PRight, aName + '2'); //Рекурсивный вызов для правого поддерева.

end;

end;

procedure TForm2.Button5Click(Sender: TObject); // Поиск

begin

if edit2.text = '' then begin

showmessage ('Ошибка! Введите значение');

exit;

end;

if FPTree = nil then begin

showmessage ('Дерево пустое!');

exit;

end;

rez:='';

find (FPTree,'0'); // Поиск

if rez = '' then

Memo1.Lines.Add('Вершина: ' + edit2.text + '; Не найдена!')

else

Memo1.Lines.Add('Вершина: ' + edit2.text + '; Адрес: ' + rez);

edit2.clear;

end;

procedure TForm2.Button6Click(Sender: TObject); // Удалить вершину

begin

if edit2.text = '' then begin

showmessage ('Ошибка! Введите значение');

exit;

end;

if FPTree = nil then begin

showmessage ('Дерево пустое!');

exit;

end;

find (FPTree,'0'); // Поиск

if rez = '' then begin

Memo1.Lines.Add('Вершина: ' + edit2.text + ' - Не найдена!');

exit

end

else begin

Memo1.Lines.Add('-----');

Memo1.Lines.Add('Вершина: ' + edit2.text + ' - Адрес: ' + rez + ' Удалена!');

Del_tree(FPTree, strtoint(edit2.text));

PaintBox1.Refresh; // Очищает рисунок фон оставляет прозрачным

Button2Click(Sender);

end;

edit2.clear;

end;

procedure TForm2.Edit1KeyPress(Sender: TObject; var Key: char); // Ограничение ввода

begin

if not (Key in ['0'..'9', #8]) then

if not (Key in ['-', #8]) then

Key := #0;

end;

procedure TForm2.Edit2KeyPress(Sender: TObject; var Key: char);

begin

if not (Key in ['0'..'9', #8]) then

if not (Key in ['-', #8]) then

Key := #0;

end;

procedure TForm2.Del_tree (var x : TPNode; y:integer); // Удаление элемента

var q:TPNode;

{Поиск самого правого элемента в дереве}

procedure Del (var w : TPNode);

begin

if w^.PRight<>nil then Del(w^.PRight)

else begin

q:=w; {Запоминается адрес для освобождения места в «куче» }

x^.data:=w^.data;

w:=w^.PLeft;

end;

end;

begin

if x<>nil then

if y<x^.data then Del_tree (x^.PLeft, y)

else if y>x^.data then Del_tree (x^.PRight, y)

else Begin

q:=x;

{Правого поддерева нет}

if x^.PRight=nil then x:=x^.PLeft

{Левого поддерева нет}

else if x^.PLeft=nil then x:=x^.PRight

else del(x^.PLeft); {Поиск самого правого элемента в левом поддереве}

dispose(q);

end;

end;

procedure TForm2.FormClose(Sender: TObject);

begin

TreeFree(FPTree); //Освобождение памяти, занятой для элементов дерева (очистка дерева).

end;

end.

Листинг программы Задание 2:

unit Unit3;

{$mode objfpc}{$H+}

Соседние файлы в папке ИПР2