Обходы бинарного дерева

Сгенерируйте бинарное дерево поиска и пройдите по шагам прямой, симметричный или обратный обход с помощью рекурсивной функции C++.

Всё моделируется в этом браузере; ничего не отправляется на сервер.

Посещает узел, затем левое поддерево, затем правое.

Функция вызывается с узлом 60

Функция вызывается с узлом 60

Бинарное дерево

60458568215532

Вывод

Ни один узел ещё не посещён

  • Не посещён
  • Выполняется
  • В стеке
  • Посещён

Шаг 1 / 44

Код

#include <iostream>
using namespace std;
class Node { // Узел хранит значение и указатели на двух потомков
private: // Приватные атрибуты: к ним обращаются только методы
int value;
Node* left;
Node* right;
public:
Node(int v) : value(v), left(nullptr), right(nullptr) {}
int getValue() const { return value; }
Node* getLeft() const { return left; }
Node* getRight() const { return right; }
void setLeft(Node* n) { left = n; }
void setRight(Node* n) { right = n; }
};
void preorder(Node* node) { // Обходит поддерево с корнем node
if (node == nullptr) return; // Базовый случай: в пустом поддереве нечего посещать
cout << node->getValue() << " "; // Посещает узел: обрабатывает его значение
preorder(node->getLeft()); // Обходит левое поддерево
preorder(node->getRight()); // Обходит правое поддерево
} // Возвращается к вызывающему коду
Node* insert(Node* root, int v) { // Вставляет v в дерево поиска и возвращает корень
if (root == nullptr) return new Node(v); // Пустое место: новый узел помещается сюда
if (v < root->getValue()) // Меньшие значения идут влево, большие — вправо
root->setLeft(insert(root->getLeft(), v));
else
root->setRight(insert(root->getRight(), v));
return root;
}
Node* buildTree() { // Строит дерево, вставляя значения по одному
int values[] = {60, 45, 85, 68, 21, 55, 32}; // Значения показанного дерева в порядке вставки
Node* root = nullptr;
for (int v : values) root = insert(root, v);
return root;
}
int main() {
Node* root = buildTree(); // Дерево из анимации, уже построенное
preorder(root); // Первый вызов, из main
cout << endl; // Конец обхода
return 0;
}

Этот инструмент генерирует бинарное дерево поиска (BST) со случайными значениями и обходит его по шагам рекурсивной функцией на C++. Вы выбираете прямой (preorder), симметричный (inorder) или обратный (postorder) обход и видите на одном дереве, когда посещается каждый узел: до потомков, между ними или после них. Узлы окрашиваются по состоянию (не посещён, выполняется, в стеке или посещён), полоса вывода показывает значения в порядке посещения, а код подсвечивает выполняемую строку. Вызовы с nullptr тоже показываются: это базовый случай, останавливающий рекурсию. Размер можно менять от 3 до 15 узлов и генерировать другое дерево. Всё имитируется в браузере.

Как пользоваться

  1. Выберите обход: Preorder, Inorder или Postorder.
  2. Измените размер дерева ползунком или нажмите «Сгенерировать новое дерево»; анимация вернётся к первому шагу.
  3. Нажмите «Пуск» или перемещайтесь кнопками предыдущего и следующего шага, при необходимости измените скорость.
  4. Следите за цветными узлами, полосой вывода с посещёнными значениями и подсвеченной строкой кода C++.

Часто задаваемые вопросы

Что такое бинарное дерево и бинарное дерево поиска?
Бинарное дерево — структура, в которой у каждого узла не более двух потомков: левый и правый. В бинарном дереве поиска (BST) значения в левом поддереве меньше значения узла, а в правом больше.
В чём разница между preorder, inorder и postorder?
Отличается момент посещения узла относительно его потомков. В preorder сначала узел, затем левое и правое поддеревья; в inorder левое поддерево, узел и правое поддерево; в postorder левое поддерево, правое поддерево и в конце узел. Preorder используют для копирования дерева, inorder для чтения BST по порядку, а postorder для освобождения или вычисления дерева, так как потомки обрабатываются раньше родителя.
Почему inorder-обход BST выдаёт отсортированные значения?
Потому что в BST всё слева от узла меньше, а всё справа больше. Посещение левого поддерева, затем узла, затем правого поддерева даёт значения от меньшего к большему.
Как реализовать рекурсивный обход на C++?
Функцией, принимающей указатель на узел. Если указатель равен nullptr, функция просто возвращается: это базовый случай. Иначе она посещает узел и вызывает себя для левого и правого потомков в порядке, нужном для данного обхода.

Похожие инструменты