Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
КП_информатика_1курс_УляшевИИ_100800.doc
Скачиваний:
98
Добавлен:
28.10.2018
Размер:
1.9 Mб
Скачать

4.Описание структуры программы:

Как и говорилось выше, программа состоит на базе сложной динамической структуры - Дерева со списками. Ниже вы видите раздел Type где описана эта сложная древовидная структура. Дерево строится по категории ПО.

type ukaz=^spisok;

spisok=record

name:string[14];

lic:string[10];

os:string[10];

lang:string[6];

razrab:string[15];

rate:string[4];

next:ukaz;

end;

uk=^derevo;

derevo=record

kat:string[12];

left,right:uk;

spisok:ukaz;

end;

В начале программы в разделе uses подключаем стандартный модуль crt для необходимости очистки экрана clrscr и для увеличения размеров окна процедурами CRTWindowSize(80,40), которая устанавливает размер окна в ширину 80 символов и в высоту 40 строк, и процедурой Window(1,1,80,40), которая определяет на экране текущее окно.

Описание переменных:

В разделе var описаны необходимые глобальные переменные.

var root:uk; //корень дерева.

k,kategor,st,filename:string; // переменные строкового типа.

fl,fl2:boolean; // переменные логического типа(флаги).

a,b,c,d,e,v,n:integer; { вспомогательные переменные целочисленного типа исп. в основном в меню и под меню.}

f:text; // текстовый файл txt.

Данная программа выполняет все основные операции с данными. Ниже написаны основные операции, их описания и процедуры:

1.Добавление программ в базу данных:

Процедура add выполняет запрос категории дерева (предварительно выделяется память под динамическую переменную), проверяется эта категория

процедурой prov_kat, если флагу присваивается значение true (такая категория уже существует в дереве) то добавляется только элементы списка к списку, а если же флаг false то вызывается процедуры zap_spis и add_spisok и категория (эл-т дерева) добавляется в дерево процедурой add_tree.

procedure add(var root:uk);

var temp:uk;

g,temp_sp:ukaz;

n:integer;

begin

fl:=false;

new(temp);

with temp^ do

begin

writeln(' .: Каталог ПО ПК :.');

write('Введите категорию ПО:');

readln(kat);

spisok:=nil;

left:=nil;

right:=nil;

end;

prov_kat(root,g,fl,temp^.kat);

if fl=true then

begin

writeln('Добавить в эту категорию данные:');

writeln('1.Да');

writeln('2.Нет');

read(n);

clrscr;

while n=1 do

begin

zap_spis(temp_sp);

g^.next:=temp_sp;

g:=g^.next;

writeln('Добавить в эту категорию данные:');

writeln('1.Да');

writeln('2.Нет');

readln(n);

clrscr;

end;

end

else

begin

writeln('Добавить в эту категорию данные:');

writeln('1.Да');

writeln('2.Нет');

read(n);

while n=1 do

begin

clrscr;

zap_spis(temp_sp);

add_spisok(temp,temp_sp);

writeln('Добавить в эту категорию данные:');

writeln('1.Да');

writeln('2.Нет');

readln(n);

end;

add_tree(temp);

end;

end;

Процедура prov_kat выполняет проверку категории, если категория уже существует

в дереве то флагу присваивается значение true и ищется конец списка g1, которая передается в программу. Имеет логарифмическую эффективность.

procedure prov_kat(var p:uk; var g1:ukaz; var fl:boolean; k:string);

begin

if p<>nil then

if p^.kat=k then begin

fl:=true;

g1:=p^.spisok;

while g1^.next<>nil do

g1:=g1^.next;

end

else

if k<p^.kat then prov_kat(p^.left,g1,fl,k)

else prov_kat(p^.right,g1,fl,k);

end;

Процедура zap_spis: создается динамическая переменная для списка и выполняется запрос элементов списка (запрос информационных полей).

procedure zap_spis(var temp_sp:ukaz);

begin

new(temp_sp);

with temp_sp^ do

begin

writeln(' .: Каталог ПО ПК :.');

write('Введите название ПО:');

readln(name);

write('Укажите какая лицензия:');

readln(lic);

write('Укажите какая OS поддеоживается:');

readln(os);

write('Введите яз[ru/en]:');

readln(lang);

write('Введите Разработчика:');

readln(razrab);

write('Введите рейтинг ПО:');

readln(rate);

next:=nil;

end;

end;

Процедура add_spisok выполняет присоединение элементов списка к элементу дерева(к категории). Добавление в список по типу стека. Имеет линейную эффективность.

procedure add_spisok(var temp:uk; var temp_sp:ukaz);

begin

if temp^.spisok=nil then

temp^.spisok:=temp_sp

else

begin

temp_sp^.next:=temp^.spisok;

temp^.spisok:=temp_sp;

end;

end;

Процедура add_tree выполняет добавление категории к двоичному дереву по правилу двоичного дерева. Имеет логарифмическую эффективность.

procedure add_tree(var temp:uk);

var p,p1:uk;

begin

if root=nil then root:=temp

else

begin

p:=root;

while p<>nil do

begin

p1:=p;

if temp^.kat<p^.kat then p:=p^.left

else p:=p^.right;

end;

if temp^.kat<p1^.kat then p1^.left:=temp

else p1^.right:=temp;

end;

end;

2.Удаление категории ПО с включенными в неё списком программ:

В основной программе запрашивается имя удаляемой категории и вызывается процедура Delete_kat. Если введенной категории нету в БД, то выводиться сообщение «Данной категории нет в БД». Процедура Delete_kat – рекурсивная процедура, которая удаляет категорию ПО (элемент дерева).

При этом удаление вершины дерева (категории) реализуется в зависимости от того, какая вершина удаляется:

1.Удаляемая вершина не содержит поддеревьев (лист). При этом удаляется ссылка на удаляемую вершину из родительской вершины.

2.Удаляемая вершина содержит одну ветвь. Для удаления необходимо скорректировать соответствующую ссылку в родительской вершине, заменив адрес удаляемой вершины адресом вершины, из нее исходящей.

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

Procedure Delete_kat(var r:Uk; kat:string);

Procedure DEL(var r:Uk; q:Uk);

Var q1:Uk;

Begin

if r^.right=nil then

begin

q^.kat:=r^.kat;

q1:=r;

r:=r^.left; dispose(q1); end

else DEL(r^.right,q);

End;

Var q:Uk;

Begin

if r=nil then writeln('Данной категории нету в БД!')

else

if kat<r^.kat then DELETE_kat(r^.left,kat)

else

if kat>r^.kat then DELETE_kat(r^.right,kat)

else

begin

if r^.right=nil then

begin

q:=r;

r:=r^.left;

dispose(q);

end

else

if r^.left=nil then

begin

q:=r;

r:=r^.right;

dispose(q);

end

else

DEL(r^.left,r);

end;

end;

3.Удаление программы из определенной категории:

В основной программе запрашивается имя категории с которой будет удаляться программа и название программы. А далее вызывается процедура spisok_del.

В случае ввода категории и названия ПО, когда их нет в БД выводится следующее сообщение «Такой категории нет в БД» или «Данной программы нет в БД!»

Процедура spisok_del – рекурсивная процедура, которая удаляет ПО из категории ПО БД.

(удаляет эл-т списка из эл-та дерева).

procedure spisok_del(p:uk;kat,k:string;var fl:boolean);

var g,g1:ukaz;

Begin

if p<>nil then

if p^.kat=kategor then

begin

fl:=true;

if p^.spisok^.next=nil then Delete_kat(root,kat)

else

begin

g1:=p^.spisok;

while (g1<>nil) and (g1^.name<>k) do

begin

g:=g1;

g1:=g1^.next;

end;

if g1=nil then writeln('Данной программы нет в БД!')

else

begin

if p^.spisok=g1 then p^.spisok:=g1^.next

else

if g1^.next=nil then g^.next:=nil

else

g^.next:=g1^.next;

end;

writeln;

end;

end

else

if kategor<p^.kat then spisok_del(p^.left,kat,k,fl)

else spisok_del(p^.right,kat,k,fl);

end;

4. Удаление всей базы данных:

При выборе этой операции будет выведено следующий запрос: «Вы действительно хотите удалить всю БД?»

Процедура Del_tree рекурсивно удаляет всю БД (уничтожает дерево).

Procedure Del_tree(var p:Uk);

Begin

If p<>nil then begin

Del_tree(p^.left);

Del_tree(p^.right);

Dispose(p);

p:=nil;

End;

End;

5. Вывод БД в виде таблицы.

Процедура vivod выводит БД на экран в виде таблицы. Процедура представляет собой рекурсивный обход дерева – слева направо (инордер).

procedure vivod(p:uk);

var g:ukaz;

begin

if p<>nil then

begin

vivod(p^.left);

g:=p^.spisok;

writeln('|------------|--------------|----------|----------|------|---------------|----|');

fl:=false;

while g<>nil do

begin

if fl=false then

begin

fl:=true;

write('|',p^.kat:12,'|');

end

else write('|','':12,'|');

write(g^.name:14,'|');

write(g^.lic:10,'|');

write(g^.os:10,'|');

write(g^.lang:6,'|');

write(g^.razrab:15,'|');

write(g^.rate:4,'|');

writeln;

g:=g^.next;

end;

vivod(p^.right);

end;

end;

Процедура poisk считывает из строки данные и присваивается строковой переменной.

procedure poisk(var st,k:string);

var poz:integer;

begin

poz:=pos(' ',st);

k:=copy(st,1,poz-1);

delete(st,1,poz);

end;

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

Процедура poisk_katрекурсивный обход дерева, выполняет вывод всех программ в виде таблицы из определенного каталога, т.е. поиск по категории ПО. В основной программе запрашивается категория, которую ищите, если же данной категории нет, то выводиться соответствующее сообщение.

procedure poisk_kat(var p:uk);

var g:ukaz;

begin

if p<>nil then

if p^.kat=kategor then

begin

g:=p^.spisok;

fl:=false;

while g<>nil do

begin

if fl=false then

begin

write('|',p^.kat:12,'|');

fl:=true;

end

else

write('|','':12,'|');

write(g^.name:14,'|');

write(g^.lic:10,'|');

write(g^.os:10,'|');

write(g^.lang:6,'|');

write(g^.razrab:15,'|');

write(g^.rate:4,'|');

writeln;

g:=g^.next;

end;

end

else

if kategor<p^.kat then poisk_kat(p^.left)

else poisk_kat(p^.right);

end;

Процедура poisk_name выполняет поиск по названию ПО и выводит в виде таблицы. Рекурсивный обход дерева – слева направо (инордер). Процедуры поиска по типу лицензии, по языку, по разработчику, по ОС и по минимальной границе рейтинга имеют аналогичный вид. Как и в случае с поиском по категории, в основной программе запрашивается имя критерии, которую ищите, если же данной критерии нет, то выводиться соответствующее сообщение.

procedure poisk_name(var p:uk);

var g:ukaz;

begin

if p<>nil then

begin

poisk_name(p^.left);

g:=p^.spisok;

fl2:=false;

while g<>nil do

begin

if g^.name=k then

begin

fl:=true;

if fl2=false then

begin

fl2:=true;

writeln('|------------|--------------|----------|----------|------|---------------|----|');

write('|',p^.kat:12,'|')

end

else write('|','':12,'|');

write(g^.name:14,'|');

write(g^.lic:10,'|');

write(g^.os:10,'|');

write(g^.lang:6,'|');

write(g^.razrab:15,'|');

write(g^.rate:4,'|');

writeln;

end;

g:=g^.next;

end;

poisk_name(p^.right);

end;

end;

7. Для хранения базы данных на внешних носителях в программе есть под меню работа с текстовыми файлами и управления над ними: считывание базы данных с текстового файла в оперативную память ПК:

Процедура readfromfile выполняет чтение из файла. Эта процедура почти идентична с процедурой add за исключением того что данные считываются с файла.

Выделяется динамическая память под категорию ПК, ищется в файле этот элемент и проверяется процедурой prov_kat существует такая категория или нет. Если существует, то добавляется только элементы списка в список, а иначе список присоединяется к элементу дерева (к категории), которая потом добавляется дерево.

Процедура poisk является вспомогательной процедурой для считывания из файла.

При выборе этой операции вам будет предложено ввести имя файла, для считывания из него информации. Если файла не существует, то программа выдаст вам сообщение, что данного файла не существует. После успешного ввода имени файла вся БД из файла считывается в оперативную память в виде дерева со списками и с ними можно работать, т.е. выполнять различные операции над ними.

Procedure readfromfile(var root:uk);

var p,p1,temp:uk;

g,g1,temp_sp:ukaz;

k:string;

begin

while not eof(f) do

begin

new(temp);

fl:=false;

readln(f,st);

poisk(st,k);

temp^.kat:=k;

prov_kat(root,g1,fl,k);

if fl=true then

begin

read_spisok(temp_sp);

g1^.next:=temp_sp;

end

else

begin

temp^.spisok:=nil;

temp^.left:=nil;

temp^.right:=nil;

read_spisok(temp_sp);

temp^.spisok:=temp_sp;

add_tree(temp);

end;

end;end;

Процедура read_spisok: создает динамическую переменную и выполняет считывание элементов списка из файла.

procedure read_spisok(var temp_sp:ukaz);

begin

new(temp_sp);

poisk(st,k);

temp_sp^.name:=k;

poisk(st,k);

temp_sp^.lic:=k;

poisk(st,k);

temp_sp^.os:=k;

poisk(st,k);

temp_sp^.lang:=k;

poisk(st,k);

temp_sp^.razrab:=k;

poisk(st,k);

temp_sp^.rate:=k;

temp_sp^.next:=nil;end;

8. Вывод (сохранение) БД в текстовый файл.

Процедура vivod_v_fail сохраняет БД в файл. Рекурсивный обход дерева – сверху вниз (преордер). В основной программе перед выводом БД требуется ввести имя файла, куда будет сохраняться БД, если файл с таким именем уже существует, то программа предложит перезаписать файл.

procedure vivod_v_fail(p:uk);

var g:ukaz;

begin

if p<>nil then

begin

g:=p^.spisok;

while g<>nil do

begin

write(f,p^.kat,' ');

write(f,g^.name,' ');

write(f,g^.lic,' ');

write(f,g^.os,' ');

write(f,g^.lang,' ');

write(f,g^.razrab,' ');

write(f,g^.rate,' ');

writeln(f);

g:=g^.next;

end;

vivod_v_fail(p^.left);

vivod_v_fail(p^.right);

end;

end;

9. Удаление файла. В данной программе можно так же удалить любой текстовый файл. При этом выполняется запрос на имя удаляемого файла. Если такого файла нет, то программа выведет соответствующее сообщение, если файл существует, программа сделает запрос «Вы действительно хотите удалить файл?» и решение будет за вами.

И так же при выходе из программы вам предлагается сохранить данные.

В общем, все процедуры связанные с обработкой двоичного дерева поиска имеют логарифмическую эффективность, кроме процедур вывода всей БД и поисков из БД, которые имеют линейную эффективность.

Для выбора нужной операции в меню нужно нажать цифру, соответствующую номеру операции и нажать на клавишу Enter.