Практика 5(СД)
.pdfpublic TreeNode Data; |
// Данные - узел дерева |
public QueueNode Next; |
// Следующий узел в очереди |
public QueueNode(TreeNode data)
{
Data = data;
Next = null;
}
}
// Простая очередь, реализованная как связный список для обхода дерева class SimpleQueue
{
private QueueNode head; |
// Голова очереди - первый элемент |
private QueueNode tail; |
// Хвост очереди - последний элемент |
// Конструктор создает пустую очередь public SimpleQueue()
{
head = null; tail = null;
}
11
// Добавляет узел в конец очереди public void Enqueue(TreeNode data)
{
QueueNode newNode = new QueueNode(data);
if (tail == null) // Если очередь пуста, голова и хвост совпадают
{
head = tail = newNode;
}
else // Иначе вставляем в хвост и обновляем ссылку
{
tail.Next = newNode; tail = newNode;
}
}
// Удаляет и возвращает узел из головы очереди, если нет элементов -
возвращает null
public TreeNode Dequeue()
{
if (head == null) return null; TreeNode data = head.Data;
head = head.Next;
12
if (head == null) tail = null;
return data;
}
// Проверяет, пуста ли очередь public bool IsEmpty()
{
return head == null;
}
}
// Класс бинарного дерева поиска с основными методами class BinarySearchTree
{
private TreeNode root; // Корень дерева
// Конструктор инициализирует пустое дерево public BinarySearchTree()
{
root = null;
}
13
// Добавляет элемент в дерево, возвращает true если добавлен успешно (нет дубликата)
public bool AddItem(int a)
{
if (root == null) |
// Если дерево пустое, создаём корень |
{ |
|
root = new TreeNode(a); return true;
}
return AddRecursive(root, a); // Иначе рекурсивно добавляем
}
// Рекурсивный метод добавления, ищет место для нового элемента private bool AddRecursive(TreeNode node, int a)
{
if (a == node.Data) |
|
return false; |
// Элемент уже есть, не добавляем дубли |
if (a < node.Data) |
// Идём в левое поддерево |
{ |
|
if (node.Left == null)
{
14
node.Left = new TreeNode(a); return true;
}
else
return AddRecursive(node.Left, a);
}
else // Идём в правое поддерево
{
if (node.Right == null)
{
node.Right = new TreeNode(a); return true;
}
else
return AddRecursive(node.Right, a);
}
}
// Удаляет элемент из дерева, возвращает true, если удаление произошло public bool RemoveItem(int a)
{
bool removed;
15
root = RemoveRecursive(root, a, out removed); return removed;
}
// Рекурсивное удаление элемента с поддержанием свойств дерева private TreeNode RemoveRecursive(TreeNode node, int a, out bool removed)
{
removed = false; |
|
if (node == null) |
|
return null; |
// Элемент не найден |
if (a < node.Data) |
// Идём в левое поддерево |
node.Left = RemoveRecursive(node.Left, a, out removed); |
|
else if (a > node.Data) |
// Идём в правое поддерево |
node.Right = RemoveRecursive(node.Right, a, out removed);
else |
|
{ |
|
removed = true; |
// Элемент найден, удаляем |
if (node.Left == null) // Если нет левого ребенка, возвращаем правого return node.Right;
else if (node.Right == null) // Если нет правого ребенка, возвращаем
левого
return node.Left;
16
//Если есть оба ребенка:
//Находим минимальный элемент в правом поддереве (наименьший потомок)
TreeNode minRight = FindMinNode(node.Right);
node.Data = minRight.Data; // Заменяем значение удаляемого узла
// Удаляем дубликат значения из правого поддерева
node.Right = RemoveRecursive(node.Right, minRight.Data, out _);
}
return node;
}
// Находит узел с минимальным значением в поддереве, идя влево private TreeNode FindMinNode(TreeNode node)
{
while (node.Left != null) node = node.Left;
return node;
}
// Очищает дерево (корень становится null) public void Clear()
{
root = null;
17
}
//Выводит дерево в консоль методом поиска в ширину (по уровням)
//Вывод дерева в консоль - поиск в ширину (уровень за уровнем)
public void Print() |
|
{ |
|
if (root == null) |
// Если дерево пустое, сообщаем об этом |
{ |
|
Console.WriteLine("(empty)");
return;
}
SimpleQueue queue = new SimpleQueue(); // Создаем пустую очередь для
обхода |
|
queue.Enqueue(root); |
// Помещаем корень дерева в очередь |
while (!queue.IsEmpty()) |
// Пока в очереди есть элементы |
{ |
|
TreeNode current = queue.Dequeue(); // Извлекаем элемент из начала очереди
Console.Write(current.Data + " "); // Выводим его значение на экран
18
// Добавляем детей текущего элемента в очередь, если они существуют
if (current.Left != null) queue.Enqueue(current.Left);
if (current.Right != null) queue.Enqueue(current.Right);
}
Console.WriteLine(); // Переход на новую строку после вывода всех элементов
}
// Поиск максимального элемента в дереве public int? FindMax()
{
if (root == null) // Если дерево пустое, возвращаем null return null;
TreeNode current = root;
// Проходим по правым потомкам, так как в бинарном дереве поиска справа содержатся большие значения
while (current.Right != null) current = current.Right;
19
// Возвращаем значение самого правого узла - максимального return current.Data;
}
// Класс с меню для взаимодействия с пользователем class Program
{
static void Main()
{
BinarySearchTree bst = new BinarySearchTree();
while (true)
{
Console.WriteLine("\nМеню:");
Console.WriteLine("1. Добавить элемент");
Console.WriteLine("2. Удалить элемент");
Console.WriteLine("3. Очистить дерево"); Console.WriteLine("4. Показать дерево (поиск в ширину)"); Console.WriteLine("5. Найти максимальный элемент");
Console.WriteLine("0. Выход");
Console.Write("Ваш выбор: ");
20
