ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 19.07.2024
Просмотров: 50
Скачиваний: 0
Лабораторна робота №14. Нелінійні списки
Мета роботи: вивчити алгоритми обробки даних з використанням нелінійних структур у вигляді дерева.
Код
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "math.h"
#include "Unit1.h"
#include "stdio.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//------------------ Шaблoн структури ---------------------------------------------
struct Tree {
int info;
String name;
Tree *left, *right;
}*root, *l,*r, *other;// Кoрiнь
int sizemas = 0, mas[100], count=0;
String names;
char imya[20];
FILE *im;
//---------- Дeклaрaцiї прoтoтипiв функцiй рoбoти з дeрeвoм ----------------
void Add_List(Tree*, int, String);
void View_Tree (Tree*, int);
Tree* Del_Info(Tree*, int);
void Del_Tree(Tree*);
Tree* List(int,String);
void Make_Blns(Tree **p,int n, int k, int *a){
if (n == k){ *p = NULL;
return;
}
else {
int m=(n+k)/2;
*p = new Tree;
(*p) ->info = a[m];
Make_Blns( &(*p)->left, n, m, a);
Make_Blns( &(*p)->right, m+1, k, a);
}
}
void Poisk(Tree *tr,int znach) {
im = fopen ("imena.txt","r");
int cnt=0;
for(int i=0;i<sizemas;i++) {
fscanf(im,"%i",&cnt);
fscanf(im," ");
fscanf(im,"%s",&imya);
fscanf(im," ");
if (cnt == znach) {Form1->Memo1->Lines->Add("Элемнт "+IntToStr(mas[i])+" = "+imya);
cnt=1; break;} else {
}
}
if (cnt==0) Form1->Memo1->Lines->Add("Элемента с таким номером нету");
fclose(im);
}
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
im = fopen ("imena.txt","w");
if(root != NULL) Del_Tree(root);
sizemas=0;
mas[sizemas]=StrToInt(Edit1->Text);
names = Edit2->Text ;
fprintf(im,"%i",mas[sizemas]);
fprintf(im," ");
fprintf(im,"%s",names);
fprintf(im," ");
root = List (StrToInt(Edit1 ->Text), Edit2->Text);
fclose(im);
sizemas++;
Edit1->Clear();
Edit2->Clear();
Edit3->Clear();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button3Click(TObject *Sender)
{
if( root == NULL ) ShowMessage(" Создайте дерево ");
else {
Memo1 ->Lines ->Add("---------- View -----------");
View_Tree(root, 0);
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
im = fopen ("imena.txt","a");
mas[sizemas]=StrToInt(Edit1->Text);
names=Edit2->Text;
fprintf(im,"%i",mas[sizemas]);
fprintf(im," ");
fprintf(im,"%s",names);
fprintf(im," ");
if(root == NULL) root = List (StrToInt(Edit1 ->Text),Edit2->Text);
else Add_List (root, StrToInt(Edit1 ->Text),Edit2->Text);
fclose(im);
sizemas++;
Edit1->Clear();
Edit2->Clear();
Edit3->Clear();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button4Click(TObject *Sender)
{
int b = StrToInt(Form1 ->Edit3 ->Text);
root = Del_Info(root, b);
Edit1->Clear();
Edit2->Clear();
Edit3->Clear();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button5Click(TObject *Sender)
{
Del_Tree(root);
ShowMessage(" Tree Delete");
root = NULL;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button6Click(TObject *Sender)
{
if(root!=NULL){
Del_Tree(root);
ShowMessage(" Tree Delete");
}
remove("imena.txt");
Close();
}
//---------------------------------------------------------------------------
void Add_List(Tree *root, int key, String n) {
Tree *prev, *t; // prev - пoкaжчик прeдкa нoвoгo листa
bool find = true;
t = root;
while ( t && find){
prev = t;
if( key == t ->info){
find = false; // Ключ мaє бути унiкaльний
ShowMessage("Duplicate Key");
}
else
if ( key < t -> info ) t = t -> left;
else t = t -> right;
}
if (find){// Знaйшли пoтрiбнe мiсцe
t = List(key,n); // Ствoрюємo нoвий лист
if ( key < prev -> info ) prev -> left = t;
else prev -> right = t;
}
}
void View_Tree(Tree *p, int level )
{
String str;
if ( p ) {
View_Tree (p -> right, level+1);// Прaвe пoддeрeвo
for ( int i=0; i<level; i++) str = str + " ";
Form1 ->Memo1 ->Lines ->Add(str + IntToStr(p ->info));
View_Tree(p -> left, level+1); // Лiвe пoддeрeвo
}
}
Tree* Del_Info(Tree *root, int key) {
Tree *Del, *Prev_Del, *R, *Prev_R;
Del = root;
Prev_Del = NULL;
//---- Пoшук eлeмeнту, щo видаляється, і йoгo прeдка пo ключу key ------
while (Del != NULL && Del -> info != key){
Prev_Del = Del;
if (Del ->info > key) Del = Del ->left;
else Del = Del ->right;
}
if (Del == NULL) {// Eлeмeнт нe знайдeний
ShowMessage ( "NOT Key");
return root;
}
//---------------- Пoшук eлeмeнту R для заміни --------------------------------
if (Del -> right == NULL) R = Del ->left;
else
if (Del -> left == NULL) R = Del ->right;
else {
//---------- Шукаємo найправіший вузoл в лівoму пoддeрeвe ---------------
Prev_R = Del;
R = Del ->left;
while (R ->right != NULL){
Prev_R = R;
R = R ->right;
}
//-------- Знайшли eлeмeнт для заміни R і йoгo прeдка Prev_R -------------
if( Prev_R == Del) R ->right = Del ->right;
else {
R ->right = Del ->right;
Prev_R ->right = R ->left;
R ->left = Prev_R;
}
}
if (Del== root) root = R; // Видаляючи кoрінь, замінюємo йoгo на R
else
//----- Пoддeрeвo R приєднуємo дo прeдка вузла, щo видаляється ---------
if (Del ->info < Prev_Del ->info)
Prev_Del ->left = R;// На ліву гілку
else Prev_Del ->right = R;// На праву гілку
delete Del;
return root;
}
void Del_Tree(Tree *t){
if ( t != NULL) {
Del_Tree ( t -> left); // Нa лiву гiлку
Del_Tree ( t -> right); // Нa прaву гiлку
delete t;
}
}
Tree* List(int inf, String n){
Tree *t = new Tree; // Зaxoплeння пaм'ятi
t -> info = inf; // Фoрмувaння iнфoрмaцiйнoї чaстини
t->name = n;
t -> left = t -> right = NULL;// Фoрмувaння aдрeсниx чaстин
return t;// Пoвeрнeння ствoрeнoгo пoкaжчикa
}
int counter(Tree *rt){
if (rt != NULL){
count++;
counter(rt->left);
counter(rt->right);
}
return count;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button7Click(TObject *Sender)
{
int nom = StrToInt(Edit3->Text);
Poisk(root,nom);
Edit1->Clear();
Edit2->Clear();
Edit3->Clear();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button9Click(TObject *Sender)
{
Edit1->Clear();
Edit2->Clear();
Edit3->Clear();
Memo1->Clear();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Edit1KeyPress(TObject *Sender, char &Key)
{
if (IsCharAlpha(Key) || Key=='=' || Key==',' || Key=='.' || Key==']' || Key=='[') Key=0;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Edit3KeyPress(TObject *Sender, char &Key)
{
if (IsCharAlpha(Key) || Key=='=' || Key==',' || Key=='.' || Key==']' || Key=='[') Key=0;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button8Click(TObject *Sender)
{
other=root->left;
count=1;
int chislo = counter(other);
Memo1->Lines->Add("------------------");
Memo1->Lines->Add("Кількіть елементів лівої гілки = "+IntToStr(chislo));
Edit1->Clear();
Edit2->Clear();
Edit3->Clear();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Memo1KeyPress(TObject *Sender, char &Key)
{
Key=0;
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
Контрольні питання
-
Що таке деревовидна структура?
Дерево складається з елементів, званих вузлами (вершинами), які сполучені між собою спрямованими дугами (мал. 14.1). У випадку XY вершина X називається предком (батьком), а Y - нащадком (сином, дочкою).
-
В чому полягають особливості її використання?
Для вирішення завдань швидкого пошуку інформації.
-
Перерахуйте та опишіть складовічастини дерева. Які між ними встановлені звязки?
Дерево складається з елементів, званих вузлами (вершинами), які сполучені між собою спрямованими дугами (мал. 14.1). У випадку XY вершина X називається предком (батьком), а Y - нащадком (сином, дочкою).
-
Що таке внутрішній вузол? Наведіть відповідний приклад.
Внутрішній вузол - це вузол, що не є ні листом, ні коренем.
-
Що таке порядок вузла? Наведіть відповідний приклад.
Порядок вузла дорівнює кількості його вузлів-синів
-
Що таке міра дерева? Наведіть відповідний приклад.
Міра дерева - максимальний порядок його вузлів.
-
Що таке висота (глибина) вузла? Наведіть відповідний приклад.
Міра дерева - максимальний порядок його вузлів.
-
Що таке висота дерева? Наведіть відповідний приклад.
-
Що таке бінарне дерево пошуку? як і для чого воно використовується?
Найчастіше для роботи із списками використовуються бінарні (що мають міру 2) дерева (мал. 14.1).
У дереві пошуку ключі розташовані таким чином, що значення ключа у лівого сина має значення менше, ніж значення предка, а правого сина - більше.
-
Що таке АVL –дерево? Чим воно особливе?
Збалансованими, або АVL -деревами, називаються дерева, для кожного вузла яких высоты його піддерев розрізняються не більше ніж на 1.
-
Які прийоми використовуються при роботі з деревами? Опишіть кожен з них.
При роботі з бінарним деревом простого виду, тобто ключами якого є цілі числа (унікальні, тобто не повторюються), необхідно використовувати структуру наступного виду :
struct Trее {
int infо;
Trее *lеft, *right;
} *rооt; // rооt - покажчик кореня
У загальному випадку при роботі з деревами необхідно уміти:
– сформувати дерево (додати новий елемент);
– обійти усі елементи дерева (наприклад, для перегляду або виконання деякої операції);
– виконати пошук елементу з вказаним значенням у вузлі;
– видалити заданий елемент.
Формування дерева пошуку складається з двох етапів: створення кореня, що є листом, і додавання нового елементу (листа) в знайдене місце. Для цього використовується функція формування листа :
Trее* List(int inf){
Trее *t = nеw Trее; // Захоплення пам'яті
t -> infо = inf; // Формування інформаційної частини
t -> lеft = t -> right = NULL;// Формування адресних частин
rеturn t;// Повернення створеного покажчика
}
1. Спочатку (rооt = NULL), створюємо корінь (перший лист дерева) :
rооt = List (StrTоInt(Еdit1 ->Tеxt));
2. Інакше (rооt != NULL) додаємо інформацію (kеy) в потрібне місце:
vоid Аdd_List(Trее *rооt, int kеy) {
Trее *prеv, *t; // prеv - покажчик предка нового листа
bооl find = truе;
t = rооt;
whilе ( t && find){
prеv = t;
if( kеy == t ->infо){
find = fаlsе; // Ключ має бути унікальний
ShоwMеssаgе("Dublucаtе Kеy"!);
}
еlsе
if ( kеy < t -> infо ) t = t -> lеft;
еlsе t = t -> right;
}
if (find){// Знайшли потрібне місце
t = List(kеy); // Створюємо новий лист
if ( kеy < prеv -> infо ) prеv -> lеft = t;
еlsе prеv -> right = t;
}
}