Files
hello-algo/ru/codes/cpp/chapter_tree/binary_search_tree.cpp
Yudong Jin 772183705e Add ru version (#1865)
* Add Russian docs site baseline

* Add Russian localized codebase

* Polish Russian code wording

* Update ru code translation.

* Update code translation and chapter covers.

* Fix pythontutor extraction.

* Add README and landing page.

* placeholder of profiles

* Use figures of English version

* Remove chapter paperbook
2026-03-28 04:24:07 +08:00

171 lines
6.6 KiB
C++

/**
* File: binary_search_tree.cpp
* Created Time: 2022-11-25
* Author: krahets (krahets@163.com)
*/
#include "../utils/common.hpp"
/* Двоичное дерево поиска */
class BinarySearchTree {
private:
TreeNode *root;
public:
/* Конструктор */
BinarySearchTree() {
// Инициализировать пустое дерево
root = nullptr;
}
/* Метод-деструктор */
~BinarySearchTree() {
freeMemoryTree(root);
}
/* Получить корневой узел двоичного дерева */
TreeNode *getRoot() {
return root;
}
/* Поиск узла */
TreeNode *search(int num) {
TreeNode *cur = root;
// Искать в цикле и выйти после прохода за листовой узел
while (cur != nullptr) {
// Целевой узел находится в правом поддереве cur
if (cur->val < num)
cur = cur->right;
// Целевой узел находится в левом поддереве cur
else if (cur->val > num)
cur = cur->left;
// Найти целевой узел и выйти из цикла
else
break;
}
// Вернуть целевой узел
return cur;
}
/* Вставка узла */
void insert(int num) {
// Если дерево пусто, инициализировать корневой узел
if (root == nullptr) {
root = new TreeNode(num);
return;
}
TreeNode *cur = root, *pre = nullptr;
// Искать в цикле и выйти после прохода за листовой узел
while (cur != nullptr) {
// Найти повторяющийся узел и сразу вернуть
if (cur->val == num)
return;
pre = cur;
// Позиция вставки находится в правом поддереве cur
if (cur->val < num)
cur = cur->right;
// Позиция вставки находится в левом поддереве cur
else
cur = cur->left;
}
// Вставка узла
TreeNode *node = new TreeNode(num);
if (pre->val < num)
pre->right = node;
else
pre->left = node;
}
/* Удаление узла */
void remove(int num) {
// Если дерево пусто, сразу вернуть
if (root == nullptr)
return;
TreeNode *cur = root, *pre = nullptr;
// Искать в цикле и выйти после прохода за листовой узел
while (cur != nullptr) {
// Найти узел для удаления и выйти из цикла
if (cur->val == num)
break;
pre = cur;
// Узел для удаления находится в правом поддереве cur
if (cur->val < num)
cur = cur->right;
// Узел для удаления находится в левом поддереве cur
else
cur = cur->left;
}
// Если узел для удаления отсутствует, сразу вернуть
if (cur == nullptr)
return;
// Число дочерних узлов = 0 или 1
if (cur->left == nullptr || cur->right == nullptr) {
// Когда число дочерних узлов = 0 / 1, child = nullptr / этот дочерний узел
TreeNode *child = cur->left != nullptr ? cur->left : cur->right;
// Удалить узел cur
if (cur != root) {
if (pre->left == cur)
pre->left = child;
else
pre->right = child;
} else {
// Если удаляемый узел является корнем, заново назначить корневой узел
root = child;
}
// Освободить память
delete cur;
}
// Число дочерних узлов = 2
else {
// Получить следующий узел после cur в симметричном обходе
TreeNode *tmp = cur->right;
while (tmp->left != nullptr) {
tmp = tmp->left;
}
int tmpVal = tmp->val;
// Рекурсивно удалить узел tmp
remove(tmp->val);
// Перезаписать cur значением tmp
cur->val = tmpVal;
}
}
};
/* Driver Code */
int main() {
/* Инициализация двоичного дерева поиска */
BinarySearchTree *bst = new BinarySearchTree();
// Обратите внимание: разные порядки вставки порождают разные двоичные деревья; данная последовательность может построить совершенное двоичное дерево
vector<int> nums = {8, 4, 12, 2, 6, 10, 14, 1, 3, 5, 7, 9, 11, 13, 15};
for (int num : nums) {
bst->insert(num);
}
cout << endl << "Исходное двоичное дерево\n" << endl;
printTree(bst->getRoot());
/* Поиск узла */
TreeNode *node = bst->search(7);
cout << endl << "Найденный объект узла = " << node << ", значение узла = " << node->val << endl;
/* Вставка узла */
bst->insert(16);
cout << endl << "После вставки узла 16 двоичное дерево имеет вид\n" << endl;
printTree(bst->getRoot());
/* Удаление узла */
bst->remove(1);
cout << endl << "После удаления узла 1 двоичное дерево имеет вид\n" << endl;
printTree(bst->getRoot());
bst->remove(2);
cout << endl << "После удаления узла 2 двоичное дерево имеет вид\n" << endl;
printTree(bst->getRoot());
bst->remove(4);
cout << endl << "После удаления узла 4 двоичное дерево имеет вид\n" << endl;
printTree(bst->getRoot());
// Освободить память
delete bst;
return 0;
}