Список использованной литературы
Ахо А., Хопкрофт Д., Ульман Дж. Структуры данных и алгоритмы. — М.: Мир, 1986.
Роберт Седжвик. Алгоритмы на C++. Фундаментальные алгоритмы. — М.: Вильямс, 2003.
Дональд Кнут. Искусство программирования. Том 3: Сортировка и поиск. — М.: Вильямс, 2002.
Джосеф А. Р. О'Рурк. Основы алгоритмов и структур данных. — СПб.: Питер, 2010.
Cormen T., Leiserson C., Rivest R., Stein C. Introduction to Algorithms. — MIT Press, 2009.
Документация по C++: https://en.cppreference.com
Документация по STL: https://cplusplus.com/reference/
Приложение
Исходный код программы:
#include <iostream>
#include <queue>
#include <vector>
#include <iomanip>
#include <locale>
#include <random>
using namespace std;
// Класс узла дерева
class TreeNode {
public:
int value; // Значение узла
TreeNode* left; // Левый ребёнок
TreeNode* right; // Правый ребёнок
TreeNode(int val) : value(val), left(nullptr), right(nullptr) {} // Конструктор узла
~TreeNode() = default; // Деструктор узла
};
// Класс двоичного дерева
class BinaryTree {
private:
TreeNode* root; // Корень дерева
// Вспомогательная функция для добавления узла в дерево
void addNode(TreeNode*& current, int value) {
if (!current) {
current = new TreeNode(value);
return;
}
if (value < current->value) {
addNode(current->left, value);
}
else {
addNode(current->right, value);
}
}
// Вспомогательная функция для ширинной разметки
void breadthMark(TreeNode* root) {
if (!root) return;
queue<TreeNode*> q;
q.push(root);
int mark = 1;
while (!q.empty()) {
TreeNode* current = q.front();
q.pop();
current->value = mark++; // Назначаем текущую метку
if (current->left) q.push(current->left);
if (current->right) q.push(current->right);
}
}
// Вспомогательная функция для внутреннего обхода (in-order)
void inOrderTraversal(TreeNode* node, vector<int>& traversal) const {
if (!node) return;
inOrderTraversal(node->left, traversal);
traversal.push_back(node->value);
inOrderTraversal(node->right, traversal);
}
// Вспомогательная функция для подсчёта узлов на нижнем уровне
int countNodesAtBottomLevel(TreeNode* root) const {
if (!root) return 0;
queue<TreeNode*> q;
q.push(root);
int count = 0;
while (!q.empty()) {
int levelSize = q.size();
count = 0;
for (int i = 0; i < levelSize; ++i) {
TreeNode* current = q.front();
q.pop();
count++;
if (current->left) q.push(current->left);
if (current->right) q.push(current->right);
}
}
return count;
}
// Вспомогательная функция для печати дерева
void printTree(TreeNode* node, int space) const {
if (!node) return;
// Увеличиваем расстояние между уровнями
space += 5;
// Сначала выводим правую ветвь
printTree(node->right, space);
// Выводим текущий узел
cout << endl;
for (int i = 5; i < space; ++i) cout << " ";
cout << node->value << "\n";
// Выводим левую ветвь
printTree(node->left, space);
}
public:
BinaryTree() : root(nullptr) {} // Конструктор по умолчанию
// Конструктор с начальным массивом значений
explicit BinaryTree(const vector<int>& values) : root(nullptr) {
for (int val : values) {
addNode(root, val);
}
}
// Деструктор дерева
~BinaryTree() {
deleteTree(root);
}
// Функция для добавления значения в дерево
void insert(int value) {
addNode(root, value);
}
// Функция для ширинной разметки
void markBreadth() {
breadthMark(root);
}
// Функция для внутреннего обхода
vector<int> inOrder() const {
vector<int> traversal;
inOrderTraversal(root, traversal);
return traversal;
}
// Функция для подсчёта узлов на нижнем уровне
int bottomLevelNodeCount() const {
return countNodesAtBottomLevel(root);
}
// Функция для печати дерева
void print() const {
printTree(root, 0);
}
// Генерация случайного дерева
void generateRandomTree(int nodeCount, int minValue, int maxValue) {
random_device rd;
mt19937 gen(rd());
uniform_int_distribution<> dist(minValue, maxValue);
for (int i = 0; i < nodeCount; ++i) {
int randomValue = dist(gen);
insert(randomValue);
}
}
private:
// Вспомогательная функция для удаления дерева
void deleteTree(TreeNode* node) {
if (!node) return;
deleteTree(node->left);
deleteTree(node->right);
delete node;
}
};
int main() {
setlocale(LC_ALL, "russian");
// Инициализация дерева
//vector<int> values = { 10, 5, 15, 3, 7, 12, 18};
//BinaryTree tree(values);
BinaryTree tree;
tree.generateRandomTree(10, 1, 100);
// Ширинная разметка
//tree.markBreadth();
// Печать дерева с разметкой
cout << "Дерево с ширинной разметкой:" << endl;
tree.print();
// Внутренний обход
vector<int> traversal = tree.inOrder();
cout << "\n\nВнутренний обход дерева: ";
for (int val : traversal) {
cout << val << " ";
}
// Подсчёт узлов на нижнем уровне
int bottomNodeCount = tree.bottomLevelNodeCount();
cout << "\n\nКоличество узлов на нижнем уровне: " << bottomNodeCount << endl;
// Инициализация дерева
int nodesCount{};
cout << "Введите кол-во узлов: ";
cin >> nodesCount;
vector<int> values;
cout << "Введите значения узлов: \n";
for (int i = 0; i < nodesCount; ++i) {
int nVal{};
cin >> nVal;
values.push_back(nVal);
}
BinaryTree tree2(values);
// Ширинная разметка
//tree2.markBreadth();
// Печать дерева с разметкой
cout << "Дерево с ширинной разметкой:" << endl;
tree2.print();
// Внутренний обход
vector<int> traversal2 = tree2.inOrder();
cout << "\n\nВнутренний обход дерева: ";
for (int val : traversal2) {
cout << val << " ";
}
// Подсчёт узлов на нижнем уровне
int bottomNodeCount2 = tree2.bottomLevelNodeCount();
cout << "\n\nКоличество узлов на нижнем уровне: " << bottomNodeCount2 << endl;
return 0;
}
