ЛР3
.docxМИНИСТЕРСТВО НАУКИ И ВЫСШЕГО ОБРАЗОВАНИЯ РОССИЙСКОЙ ФЕДЕРАЦИИ
федеральное государственное автономное образовательное учреждение высшего образования
«САНКТ-ПЕТЕРБУРГСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ АЭРОКОСМИЧЕСКОГО ПРИБОРОСТРОЕНИЯ»
КАФЕДРА № 53
ОТЧЕТ ЗАЩИЩЕН С ОЦЕНКОЙ
ПРЕПОДАВАТЕЛЬ
ассистент |
|
|
|
М.П. Агеев |
должность, уч. степень, звание |
|
подпись, дата |
|
инициалы, фамилия |
ОТЧЕТ О ЛАБОРАТОРНОЙ РАБОТЕ № 3 |
||||
БИНАРНОЕ ДЕРЕВО |
||||
по курсу: ТЕХНОЛОГИИ ПРОГРАММИРОВАНИЯ |
||||
|
||||
|
РАБОТУ ВЫПОЛНИЛА
СТУДЕНТКА ГР. № |
|
|
|
|
|
|
|
|
подпись, дата |
|
инициалы, фамилия |
Санкт-Петербург 2021
Цель работы
Построение и изучение возможностей бинарного дерева.
Задание
Разработать программу, принимающую на вход числовую
последовательность для построения бинарного дерева. Программа должна предоставлять следующий функционал:
1. Поиск элемента в заданном дереве (макс. 5 баллов);
2. Удаление/ добавление элемента (макс. 5 баллов);
3. Графическое представление дерева (макс. 5 баллов).
Листинг программы
namespace ConsoleApp1
{
class BinaryTree
{
private TreeNode root;
public TreeNode Find(int data)
{
if (root != null) /*если root не нулевой, тогда ищем нужный узел*/
{
return root.Find(data);
}
else
{
return null;
}
}
public void Insert(int data) //добавление числа
{
if (root != null) // если root не нулевой, то добавляем
{
root.Insert(data);
}
else
{
root = new TreeNode(data); // если root нулевой, то задаем его новым узлом
}
}
public void Insert2(TreeNode ToInsert, int data) // добавление узла
{
root.Insert2(ToInsert, data);
}
public int SoftDelete(int data)
{
bool stop = false;
bool left = false;
TreeNode current = root.Find(data); // то, что хотим удалить
TreeNode parent = root; // для поиска узла-родителя
if ((parent.LeftNode != null) && (parent.RightNode != null))
{
while (!stop)
{
if ((current.Data < parent.Data) && (parent.LeftNode.Data != current.Data) && (parent.RightNode.Data != current.Data))
{
parent = parent.LeftNode;
}
else
{
if (parent.LeftNode.Data == current.Data)
{
if ((current.LeftNode == null) && (current.RightNode == null))
{
root.LeftNode = null;
return Height();
}
else
{
stop = true;
left = true;
break;
}
} else
{
if (parent.RightNode.Data == current.Data)
{
if ((current.LeftNode == null) && (current.RightNode == null))
{
root.RightNode = null;
return Height();
} else
{
stop = true;
break;
}
}
}
parent = parent.RightNode;
}
if (parent.LeftNode != null)
{
if (parent.LeftNode.Data == data)
{
stop = true;
left = true;
}
else
{
if (parent.RightNode != null)
{
if (parent.RightNode.Data == data)
{
stop = true;
}
}
}
}
}
} else
{
root = null;
}
// присоединение веток
if (left)
{
parent.LeftNode = current.RightNode;
if (current.LeftNode != null)
{
Insert2(current.LeftNode, current.LeftNode.Data);
}
return Height();
} else
{
parent.RightNode = current.RightNode;
if (current.LeftNode != null)
{
Insert2(current.LeftNode, current.LeftNode.Data);
}
return Height();
}
}
public int Height()
{
if (root == null)
{ return 0; } // если root нулевой, то и количество уровней = 0
return root.Height();
}
//private int level = -1;
public void ToList(ref List<List<int>> nodes, int x)
{
if (root != null)
{
TreeNode current = root.Find(x); //current - это текущий узел
root.ToList(current, ref nodes); // ref nodes - это указатель на list с узлами
}
}
}
public class TreeNode
{
private int data; //data - значение (само число)
public int Data
{
get { return data; }
}
private TreeNode rightNode; //узел справа снизу
public TreeNode RightNode
{
get { return rightNode; }
set { rightNode = value; }
}
private TreeNode leftNode; //узел слево снизу
public TreeNode LeftNode
{
get { return leftNode; }
set { leftNode = value; }
}
public TreeNode(int value) //конструктор самого узла
{
data = value;
}
public TreeNode Find(int value)
{
TreeNode currentNode = this; //текущий узел
while (currentNode != null) //пока не дошел до края
{
if (value == currentNode.data/* && isDeleted == false*/)
{
return currentNode; //вернет узел, когда найдет совпадение
}
else if (value > currentNode.data)
{
currentNode = currentNode.rightNode; //если значение больше, чем у текущего, то уходим вправо
}
else
{
currentNode = currentNode.leftNode; // иначе идем влево
}
}
return null; //если совпадений не найдено
}
public void Insert(int value)
{
if (value >= data)
{
if (rightNode == null)
{
rightNode = new TreeNode(value); //если значение больше и справа пусто, то ставим туда
}
else
{
rightNode.Insert(value); //если справа что-то есть, то просто переходим туда и ищем дальше
}
}
else
{
if (leftNode == null)
{
leftNode = new TreeNode(value); //если значение меньшн и слево пусто, то ставим туда
}
else
{
leftNode.Insert(value); //если слево что-то есть, то просто переходим туда и ищем дальше
}
}
}
public void Insert2(TreeNode ToInsert, int value)
{
if (value >= data)
{
if (rightNode == null)
{
rightNode = ToInsert; //если значение больше и справа пусто, то ставим туда
}
else
{
rightNode.Insert2(ToInsert ,value); //если справа что-то есть, то просто переходим туда и ищем дальше
}
}
else
{
if (leftNode == null)
{
leftNode = ToInsert; //если значение меньшн и слево пусто, то ставим туда
}
else
{
leftNode.Insert2(ToInsert, value); //если слево что-то есть, то просто переходим туда и ищем дальше
}
}
}
public int Height()
{
if (this.leftNode == null && this.rightNode == null)
{
return 1; // вернет 1, когда найдет край
}
int left = 0;
int right = 0;
if (this.leftNode != null)
left = this.leftNode.Height(); //если слево есть узел, переходим в него
if (this.rightNode != null)
right = this.rightNode.Height(); //и наоборот
if (left > right)
{
return (left + 1);
}
else
{
return (right + 1);
}
}
private int level = -1;
public void ToList(TreeNode current, ref List<List<int>> nodes)
{
level++; //отвечает за уровень, на который добавляем
nodes[level].Add(current.data); // иначе добавим просто само значение
if (current.leftNode != null)
{
ToList(current.leftNode, ref nodes);
} else nodes[level+1].Add(-2); // -2 это особое значение, вместо которого потом будет пустое окошко
if (current.rightNode != null)
{
ToList(current.rightNode, ref nodes);
} else nodes[level+1].Add(-2);
level--;
}
}
using System;
using System.Collections.Generic;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
BinaryTree binaryTree = new BinaryTree(); //создаем экземпляр бинарного дерева
List<List<int>> nodes = new List<List<int>>(); // узлы
bool first = true; //для сохранения первого элемента
int IntFirst = -1;
bool stop = false;
while (!stop)
{
Console.WriteLine($"Введите число или '-1' для выхода");
string str = Console.ReadLine();
if (str != "-1" && str.Length > 0)
{
bool stop2 = false;
for (int i = 0; i < str.Length; i++)
{
if (str[i] >= '0' && str[i] <= '9') //проверка ввода
{
} else
{
stop2 = true;
}
}
if (!stop2)
{
if (Convert.ToInt32(str) >= 0 && Convert.ToInt32(str) <= 99)
{
binaryTree.Insert(Convert.ToInt32(str)); // добавление
if (first)
{
IntFirst = Convert.ToInt32(str);
first = false;
}
}
else
{
Console.WriteLine($"Ошибка");
}
}
else
{
Console.WriteLine($"Ошибка");
}
} else
{
stop = true;
}
}
if (IntFirst != -1) //если есть хоть один элемент
{
int height = binaryTree.Height();
for (int i = 0; i < height+2; i++)
{
nodes.Add(new List<int>()); //создаем уровни
}
bool deleting = true;
bool stop3 = false;
while (deleting)
{
Console.WriteLine($"Для удаления элемента введите del иначе введите 0");
string ans = Console.ReadLine();
if (ans == "del")
{
Console.WriteLine($"Выберете элемент");
string ans2 = Console.ReadLine();
for (int i = 0; i < ans2.Length; i++)
{
if (ans2[i] >= '0' && ans2[i] <= '9') //проверка ввода
{
}
else
{
stop3 = true;
}
}
if (!stop3)
{
if (binaryTree.Find(Convert.ToInt32(ans2)) != null)
{
height = binaryTree.SoftDelete(Convert.ToInt32(ans2));
}
}
}
else
{
deleting = false;
}
}
binaryTree.ToList(ref nodes, IntFirst); /*IntFirst - первое значение а через ToList загоняем все nodes в List*/
int width = Convert.ToInt32(Math.Pow(2, height - 1)*4 - 3); //считаем ширину по самому низу
Console.WriteLine($"Вывод дерева:");
if (nodes.Count > 1)
{
for (int i = 0; i < height; i++) //идем по уровням
{
for (int j = 0; j < Math.Pow(2, i); j++)
{
for (int y = 0; y < width / Math.Pow(2, i + 1) - 1; y++)
{
Console.Write($" "); // это как раз расстояния между числами (этот перед числом)
}
if (j < nodes[i].Count && nodes[i][j] != -2)
{
if (nodes[i][j].ToString().Length > 1)
{
Console.Write($"{nodes[i][j]}"); // вывод двузначного числа
}
else
{
Console.Write($"{nodes[i][j]} "); // вывод числа с одним знаком
}
}
else
{
Console.Write($" "); // пустые места заменяются на пробелы, и под пустыми местами добавляются пробелы
nodes[i + 1].Insert(j * 2, -2);
nodes[i + 1].Insert(j * 2 + 1, -2);
}
for (int y = 0; y < width / Math.Pow(2, i + 1) - 1; y++)
{
Console.Write($" "); //(это после числа)
}
}
Console.WriteLine($""); Console.WriteLine($""); //расстояния между уровнями
}
}
} else
{
Console.WriteLine($"Значения отстуствуют");
}
}
}
}
Результат работы программы
На рисунке 1 представлен результат работы программы.
Рисунок 1 –Результат работы программы
Вывод
В ходе выполнения лабораторной работы были изучены теоретические материалы для построения бинарного дерева. Также была разработана программа, которая принимают на вход числовую последовательность. Программа предоставляет поиск элемента в заданном дереве, удаление/добавление элемента.