Вы находитесь на странице: 1из 15

ТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ МОЛДОВЫ

Факультет информатики, вычислительной техники и


микроэлектроники

Департамент Информатики и Системной Инженерии

Отчёт
По лабораторной работе №5,
SDA

Chisinau – 2020
Лабораторная работа 5
Тема: Абстрактный тип данных «Бинарное дерево». Использование
итеративных алгоритмов
Цель работы:
Изучение возможностей и средств языка Си для реализации и использования основных
операций обработки бинарного дерева при обходе узлов дерева в ширину и в глубину с
использованием очереди и стека.

Задание, вариант 4:
Составить три файла на языке Си для реализации и использования АТД «Бинарное
дерево» с обеспечением операций обработки дерева при обходе узлов дерева с
помощью итерационных алгоритмов.

1. Заголовочный файл с расширением .h для описания структуры данных узла дерева


(по вариантам), а также для прототипов функций, обеспечивающих операции обработки
дерева.

2. Файл с расширением .cpp для определений функций (текстов функций),


объявленных в заголовочном файле.

3. Файл пользователя - функцию mаin () для обработки дерева с выводом на экран


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

Структура КИНОТЕАТР с полями: название, адрес, телефон, количество мест, цена


билетов.

Решение:
Исходный код программы:
main.cpp
/*
* Lab #5 (10)
* SI-192 Comanac Artiom*/

#include "wrapper.h"
#include <locale.h>

using namespace std;

int main() {
setlocale(LC_ALL, "RUS");
int choice = 0;
CinemaTree* BTree = new CinemaTree();

while (true) {
Console::printMenu();
cin >> choice;
system("cls");

if (!BTree && choice < 8) {


choice = -1;
}

switch (choice) {
case 1:
BTree->addElement();
break;

case 2:
BTree->printTree();
break;

case 3:
BTree->searchElById();
break;

case 4:
BTree->searchElByTitle();
break;

case 5:
Console::print("Количество элементов дерева: " +
to_string(BTree->getElCount()));
break;

case 6:
Console::print("Высота дерева: " +
to_string(BTree->getHeight()));
break;

case 7:
delete BTree;
BTree = nullptr;
Console::print("Память очищена");
break;

case 8:
exit(0);
break;

case 17:
if (BTree) {
cout << "Память еще не была очищена,
возможен вывод неверной информации" << "\n";
system("pause");
}

_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
_CrtSetReportFile(_CRT_WARN,
_CRTDBG_FILE_STDOUT);
if (!_CrtDumpMemoryLeaks()) {
Console::print("Утечки памяти отсутствуют");
}
break;

case -1:
Console::printError(5);
break;

default:
Console::printError(4);
break;
}

Console::menu();
}

//
}

wrapper.h
/*
* Header file for Struct Cinema and functions
* SI-192 Comanac Artiom*/

#ifndef WRAPPER_H_
#define WRAPPER_H_

#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#include <queue>
#include <sstream>

#ifdef _DEBUG
#define new new( _NORMAL_BLOCK , __FILE__ , __LINE__ )
#else
#define new new
#endif

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <fstream>
#include <string>

using namespace std;

/*
* Класс Консоль, для обработчика программы
*/
class Console {
public:
static string getError(int);
static void printError(int);
static void menu();
static void print(const string);
static void printMenu();
};

/*
* Класс Кинтотеатр
*/
class Cinema {
public:
string title;
string address;
string phone;
int quantity;
int price;
void input();

friend class Branch;


};

/*
* Класс Ветка
*/
class Branch {
public:
Branch(int, Cinema*);
~Branch();
int id;
Cinema* cell = nullptr;
Branch* left = nullptr;
Branch* right = nullptr;

friend class CinemaTree;


};

/*
* Класс "Бинарное дерево классов <Ветка>"
*/
class CinemaTree {
private:
Branch* head = nullptr;
int elements = 0;

bool _new(int, Cinema*);


bool _checkId(int);
int _height(Branch*);
void _print(Branch*, int);
Branch* _searchId(int);
Branch* _searchTitle(string);
public:
CinemaTree();
~CinemaTree();
void addElement();
void printTree();
int getHeight();
int getElCount();
void printBranch(Branch*);
void searchElById();
void searchElByTitle();

};

#endif
functions.cpp
#include "wrapper.h";

using namespace std;


const char* SPLIT = "-------------------------------------------
-----------";

/*
* Реализация класса Консоль
* class Console
*/
/*
* Пауза для меню*/
void Console::menu() {
system("pause");
system("cls");
}

/*
* Вывод системных сообщений*/
void Console::print(const string message) {
cout << "\n" << SPLIT;
cout << "\n" << message;
cout << "\n" << SPLIT << endl;
}

/*
* Вывод меню*/
void Console::printMenu() {
cout << "\n" << SPLIT;
cout << "\n1.\tСоздать узел";
cout << "\n2.\tВывести узлы на экран";
cout << "\n3.\tПоиск узла по ID";
cout << "\n4.\tПоиск узла по Названию";
cout << "\n5.\tКоличество узлов";
cout << "\n6.\tВысота дерева";
cout << "\n7.\tОсвобождение памяти";
cout << "\n8.\tОкончание работы программы";
cout << "\n17.\tПроверка утечек памяти";
cout << "\n" << SPLIT << endl;
cout << "Выберите пункт меню: ";
};

/*
* Ошибка по коду*/
string Console::getError(int ecod) {
switch (ecod) {
case 1:
return "Указанный ID уже используется";

case 3:
return "Элемент не найден";

case 4:
return "Пункт меню не найден";

case 5:
return "Память очищена, доступен только 8 пункт меню";

default:
return "Неожиданная ошибка";
}
}

/*
* Вывод ошибки по коду (на экран)*/
void Console::printError(int ecod)
{
Console::print(
Console::getError(ecod)
);
}

/*
* Реализация класса-структуры Кинотеатр
* class Cinema
*/

/*
* Ввод элемента Кинотеатр
*/
void Cinema::input() {
cout << "Создание нового элмента типа Кинотеатр..." <<
endl;
cout << "Название: "; cin >> title;
cout << "Адрес: "; cin >> address;
cout << "Телефон: "; cin >> phone;
cout << "Количество мест: "; cin >> quantity;
cout << "Цена: "; cin >> price;
cout << "Успешно" << endl;
}

/*
* Реализация класса-структуры Ветка
* class Branch
*/
Branch::Branch(int id, Cinema* cell) {
this->id = id;
this->cell = cell;
}

/*
* Деструктор Branch
*/
Branch::~Branch() {
delete cell;
}

/*
* Реализация класса Дерево
* class CinemaTree
*/

CinemaTree::CinemaTree() {
head = new Branch(-1, nullptr);
head->cell = nullptr;
head->id = -1;
}

/*
* Добавление нового элемента в дерево
*/
bool CinemaTree::_new(int id, Cinema* cell) {
Branch* list = head;

while (list->left || list->right) {


if (list->id > id) {
if (!list->left)
break;
list = list->left;
}
else if (list->id < id) {
if (!list->right)
break;
list = list->right;
}
}

if (list->id == -1) {
//первый элемент
list->id = id;
list->cell = cell;
}
else {
if (list->id > id)
list->left = new Branch(id, cell);
else
list->right = new Branch(id, cell);
}

elements++;

return true;
}

/*
* Проверка на существование указанного ID в дереве
*/
bool CinemaTree::_checkId(int id) {
Branch* list = head;

while (list->left || list->right) {


if (list->id == id)
return false;

if (list->id > id) {


if (!list->left)
break;
list = list->left;
}
else if (list->id < id) {
if (!list->right)
break;
list = list->right;
}
}

if (list->id == -1 || list->id != id)


return true;
else
return false;
}

/*
* Создание нового элемента дерева
*/
void CinemaTree::addElement() {
int id;
cout << "Укажите ID нового элемента: ";
cin >> id;
if (!_checkId(id)) {
cout << Console::getError(1) << endl;
return;
}
Cinema* el = new Cinema();
el->input();

_new(id, el);
}

/*
* Высота дерева [private]
*/
int CinemaTree::_height(Branch* list) {
if (!list)
return 0;
else {
if (list->id == -1)
return 0;

return max(_height(list->left), _height(list->right))


+ 1;
}
}

/*
* Обработчик функции подсчета высоты дерева [public]
*/
int CinemaTree::getHeight() {
return _height(head);
}

/*
* Вывод ветки дерева на экран
*/
void CinemaTree::printBranch(Branch* el) {
ostringstream el_pointer, pointer_left, pointer_right;
el_pointer << el;
pointer_left << el->left;
pointer_right << el->right;

Console::print(
"ID [адрес]: " + to_string(el->id) + " [" +
el_pointer.str() + "]" "\n" +
"Название: " + el->cell->title + "\n" +
"Адрес: " + el->cell->address + "\n" +
"Телефон: " + el->cell->phone + "\n" +
"Количество мест: " + to_string(el->cell->quantity) +
"\n" +
"Цена: " + to_string(el->cell->price) + "\n" +
"Левая ветка: " + pointer_left.str() + "\n" +
"Правая ветка: " + pointer_right.str()
);
}

/*
* Вывод элементов дерева на экран
*/
void CinemaTree::_print(Branch* list, int spaces = 0) {
queue<Branch*> q;
q.push(list);
while (!q.empty()) {
Branch* temp = q.front();
q.pop();

printBranch(temp);

if (temp->left)
q.push(temp->left);

if (temp->right)
q.push(temp->right);
}
}

/*
* Количество элементов в дереве
*/
int CinemaTree::getElCount() {
return elements;
}

/*
* Обработчик вывода дерева на экран
*/
void CinemaTree::printTree() {
if (elements > 0)
_print(head);
else
Console::print("Элементы отсутствуют");
}

/*
* Поиск элемента дерева по ID
*/
Branch* CinemaTree::_searchId(int id) {
Branch* list = head;

queue<Branch*> q;
q.push(list);
while (!q.empty()) {
Branch* temp = q.front();
q.pop();

if (temp->id == id)
return temp;

if (temp->left)
q.push(temp->left);

if (temp->right)
q.push(temp->right);
}

return nullptr;
}

/*
* Поиск элемента дерева по Названию
*/
Branch* CinemaTree::_searchTitle(string query) {
Branch* list = head;

queue<Branch*> q;
q.push(list);
while (!q.empty()) {
Branch* temp = q.front();
q.pop();

if (temp->cell->title == query)
return temp;

if (temp->left)
q.push(temp->left);

if (temp->right)
q.push(temp->right);
}

return nullptr;
}

/*
* Обработчик поиска элемента дерева по ID
*/
void CinemaTree::searchElById() {
int id;
cout << "Поиск по ID: ";
cin >> id;
Branch* el = _searchId(id);
if (el)
printBranch(el);
else
Console::printError(3);
}

/*
* Обработчик поиска элемента дерева по Названию
*/
void CinemaTree::searchElByTitle() {
string query;
cout << "Поиск по Названию: ";
cin >> query;

Branch* el = _searchTitle(query);
if (el)
printBranch(el);
else
Console::printError(3);
}

/*
* Деструктор CinemaTree
*/
CinemaTree::~CinemaTree() {
queue<Branch*> q;
q.push(head);
while (!q.empty()) {
Branch* temp = q.front();
q.pop();

if (temp->left)
q.push(temp->left);

if (temp->right)
q.push(temp->right);

delete temp;
}
}

Результаты работы программы:

Главное меню
Вывод элементов на экран

Реализован вывод исключений в виде ошибок, поиск элементов бинарного дерева по ID /


Названию с использованием стека. Для оптимизации есть пункт «Проверка утечек
памяти», при помощи которого производится проверка на утечки памяти.

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

Оценить