Professional Documents
Culture Documents
лба3
лба3
Лабораторна робота № 3
«БІНАРНІ ДЕРЕВА»
Курс: АЛГОРИТМИ ТА СТРУКТУРИ ДАНИХ
Варіант
Виконав:
Студент групи ТА–,ТЕФ
Перевірив:
Київ 2022
Мета роботи: Вивчити принципи побудови абстрактних типів даних типу
бінарне дерево та алгоритми їх обробки мовою процедурного програмування
Сі.
1.Теоретичні відомості
3. Схема алгоритму
3.1 Схема алгоритму до функції пошуку
int main()
if (!temp) {
puts("Помилка виділення пам'яті");
return 0;
}
char filename[256];
char tempdata[256];
int howmany;
int menu;
int initm;
int findkey;
int removekey;
int swork;
SetConsoleCP(1251);
SetConsoleOutputCP(1251);
do {
switch (menu)
{
case 0:
tree = InitTree();
if (InitTree == NULL)
{
puts("Something went wrong");
exit(0);
}
puts("Створено!");
break;
case 1: {
if (!tree)
{
puts("Дерева не існує");
break;
case 1:
puts("Скільки елементів хочете додати ?");
scann(howmany);
puts("Введіть рядок");
int flag = 0;
do {
fgets(tempdata, 1024, stdin);
if (tempdata[0] == '\n' && flag == 1) {
printf("Текст не повинен бути пустим, спробуйте ще раз:");
}
flag = 1;
} while (tempdata[0] == '\n');
if (tree->root == NULL)
{
tree->root = ElemAdd(tree, tree->root, tempdata);//додавання елементів
}
else
{
ElemAdd(tree, tree->root, tempdata);
}
if (ElemAdd == NULL)
{
puts("Something went wrong");
exit(0);
}
}
puts("Додано!");
break;
case 2:
}
puts("Додано!");
break;
}
break;
}
case 2:
{
if (!tree)
{
puts("Дерева не існує");
break;
puts("1.Симетричний\n2.Прямий\n3.Зворотній");
scann(initm);
switch (initm) {
case 1:
puts("Симетричний:\n");
inOrder(tree->root);
break;
case 2:
puts("Прямий:\n");
preOrder(tree->root);
break;
case 3:
puts("Зворотній:\n");
postOrder(tree->root);
break;
}
puts("Виведено!");
break;
}
case 3:
{
if (!tree)
{
puts("Дерева не існує");
break;
puts("Введіть рядок");
int flag = 0;
do {
fgets(tempdata, 1024, stdin);
if (tempdata[0] == '\n' && flag == 1) {
printf("Текст не повинен бути пустим, спробуйте ще раз:");
}
flag = 1;
} while (tempdata[0] == '\n');
}
puts("1)Без дескриптора\n2)З дескриптором");
int cle_tree;
scanf("%d", &cle_tree);
if (cle_tree == 1)
{
clear_Tree(tree->root);
}
else if (cle_tree == 2)
{
clear_Tree(tree->root);
free(tree);
tree = NULL;
}
if (clear_Tree == NULL)
{
puts("Something went wrong");
exit(0);
}
puts("Очищено!");
break;
}
case 5:
{
if (!tree)
{
puts("Дерева не існує");
break;
puts("Введіть рядок");
int flag1 = 0;
do {
fgets(tempdata, 1024, stdin);
if (tempdata[0] == '\n' && flag1 == 1) {
printf("Текст не повинен бути пустим, спробуйте ще раз:");
}
flag1 = 1;
} while (tempdata[0] == '\n');
temproot = ElemSearch(tree->root, tempdata);
if (temproot != NULL)
{
tree->root = ElemRemove(tree->root, tempdata);
tree->size--;
}
else
{
puts("Done!");
break;
}
case 6:
if (!tree)
{
puts("Дерева не існує");
break;
}
if (tree->root == NULL)
{
printf("Створено лише дескриптор!\n");
break;
}
puts("Введіть назву файлу:");
do {
fgets(filename, 1024, stdin);
if (filename[0] == '\n') {
printf("Текст не повинен бути пустим, спробуйте ще раз:");
}
} while (filename[0] == '\n');
filename[strlen(filename) - 1] = '\0';
if (filename[strlen(filename) - 4] != '.' && filename[strlen(filename) - 3] !=
'b' && filename[strlen(filename) - 2] != 'i' &&
filename[strlen(filename) - 1] != 'n') {
strcat(filename, ".bin");
}
if ((fp = fopen(filename, "wb+")) == NULL)
{
printf("Виникла помилка при відкритті файлу %s! \n", filename);
return 1;
}
printfile(fp, tree->root);
if (fclose(fp) == EOF)
{
printf("Виникла помилка при закритті файлу %s! \n", filename);
return 1;
}
puts("Записано!");
break;
case 7:
if (!tree)
{
tree = InitTree();
}
clear_Tree(tree->root);
puts("Введіть назву файлу:");
do {
fgets(filename, 1024, stdin);
if (filename[0] == '\n') {
printf("Текст не повинен бути пустим, спробуйте ще раз:");
}
} while (filename[0] == '\n');
filename[strlen(filename) - 1] = '\0';
if (filename[strlen(filename) - 4] != '.' && filename[strlen(filename) - 3] !=
'b' && filename[strlen(filename) - 2] != 'i' && filename[strlen(filename) - 1] != 'n') {
strcat(filename, ".bin");
}
if ((fp = fopen(filename, "rb")) == NULL)
{
printf("Виникла помилка при відкритті файлу %s! \n", filename);
return 1;
}
tree = TreeReadFromFile(fp, tree);
if (fclose(fp) == EOF)
{
printf("Виникла помилка при закритті файлу %s! \n", filename);
return 1;
}
puts("Зчитано!");
break;
case 8:
if (!tree)
{
puts("Дерева не існує");
break;
}
int height;
height = height_tree(tree->root);
printf("Висота дерева : %d\nК-сть елементів: %d\n", height, tree->size);
break;
case 9:
if (!tree) {
puts("Дерева не існує");
break;
if (GetSize(tree) == 0)
{
puts("Дерево порожнє,к-сть вузлів 0");
}
else
{
puts("Дерево не порожнє");
}
break;
case 10:
return 0;
break;
case 11:
if (!tree) {
puts("Дерева не існує");
break;
}
system("cls");
prepare_print(tree->root);
break;
case 12:
system("cls");
break;
}
_getch();
return 0;
DescTree* InitTree(void) {
DescTree* dsBST;
dsBST = (DescTree*)malloc(sizeof(DescTree));
if (!dsBST) {
return NULL;
}
dsBST->root = NULL;
dsBST->size = 0;
return dsBST;
}
strcpy(data, tempdata);
if (!subTree) {
subTree = (TreeNode*)malloc(sizeof(TreeNode));
if (!subTree)
{
return NULL;
}
int tmp;
if (!(subTree->key = (char*)malloc(sizeof(char) * (strlen(data) + 1))))
{
return NULL;
}
subTree->key = data;
}
else if (strcmp(subTree->key, tempdata) == -1)
{
subTree->right = ElemAdd(dsTree, subTree->right, data);//пірнаємо у праве піддерево
}
return subTree;
}
root->key = temp->key;
}
return root;
}
fprintf(fp, "%s\n",tree->key);
printfile(fp, tree->left);
printfile(fp, tree->right);
}
return;
}
rewind(fp);
for (int i = 0; i <= file_size; i++)
{
if (fscanf(fp, "%s\n", tdata) != 1) {
return tree;
}
if (tree->root == NULL)
{
tree->root = ElemAdd(tree, tree->root,tdata);
}
else
{
ElemAdd(tree, tree->root, tdata);
}
}
return tree;
}
int scann(int& N)
{
int isEntered = 0;
do {
do {
isEntered = scanf_s("%d", &N);// перевірка на те що введене значення є числом
while (getchar() != '\n');
while (isEntered < 1) {
printf("Ви ввели некоректне значення,повторіть введення: ");
isEntered = scanf_s("%d", &N);
while (getchar() != '\n');
}
} while (isEntered < 1);
} while (isEntered != 1);
return N;
}
{
int quant = 0;
while (!feof(fd))
{
fscanf(fd, "%*[^\n]\n");//ігноруємо перехід на іншу строку
quant++;
}
rewind(fd);//перематуємо файл
return quant;
}
if (tree == NULL)
return;
depth++;
if (direction)
path[depth - 2] = 1;
if (tree->left)
path[depth - 1] = 1;
printf("\n");
printf("%s\n", tree->key);
5.Тестування програми
Рис 5.1 Робота програми при невірному введенні пункта меню
Рис 5.2 Створення дерева та його вивід
Рис 5.3 Додавання елементів до дерева з файлу та вивід за допомогою
обходу
Рис 5.4 Видалення вершини дерева
Рис 5.5 Пошук вершини ( що є в дереві та відсутня в ньому)
Висновок
На цій лабораторній роботі було вивчено принципи побудови
абстрактних типів даних типу бінарне дерево та алгоритмів їх обробки
мовою процедурного програмування Сі.
В результаті була написана програма результатом роботи якої є
бінарне дерево пошуку, елементом якого є рядок.
При виконанні лабораторної роботи було виявлено проблему виділення
пам'яті під вузол. З цією проблемою стикався у 2 лабораторній роботі.
Проблему було вирішено створивши в функції main тимчасовий масив в
який ми записуємо рядок, потім, в функції додавання рядка створюємо
динамічний масив, що має розмір тимчасового масиву,і потім вже працюємо
з нашим динамічним масивом. Програму було багаторазово протестованого і
я переконався, що проблема більш не виникає.
Дану програму можна використовувати для роботи з бінарним деревом
пошуку. Доповнивши програму можна буде повноцінно використовувати всі
можливості бінарного дерева пошуку, а саме додавши ще одну функцію
можна буде зливати 2 дерева в одне.
Порівнюючи дерева з іншими АТД можна сказати що використання
бінарного дерева пошуку є дуже зручним при роботі з усіма типами данних.
Також робота з ключем дає нам можливість шукати та виводити
значення за ключем, що зменшує час пошуку.
Роблячи висновок дерево пошуку дає змогу дуже зручно зберігати,
шукати та сортувати записувані в нього значення.