Обход Морриса (InOrder) — это алгоритм обхода дерева, который не использует рекурсию или стек. В этом обходе ссылки создаются как преемники, и узлы печатаются с использованием этих ссылок. Наконец, изменения отменяются, чтобы восстановить исходное дерево.
Алгоритм
-
Инициализировать
root
как текущий узелcurr
. -
Пока
curr
неNULL
проверьте, есть ли уcurr
левый дочерний элемент. -
Если
curr
не имеет левый дочерний элемент, выведитеcurr
и обновите его, чтобы он указывал на узел справа отcurr
. -
Иначе, сделайте
curr
правым потомком самого правого узла в левом поддеревеcurr
. -
Обновите
curr
до этого левого узла.
Демо
Давайте возьмем двоичное дерево, приведенное ниже, и пройдемся по нему. обход Морриса (InOrder).
4 4 4 — это корень, поэтому он инициализируется как curr
. 44 4 имеет левый дочерний элемент, поэтому он становится самым правым дочерним элементом своего левого поддерева (непосредственный предшественник 4 4 4 в обходе InOrder). Наконец, 44 4 становится правым потомком 33 3 и curr
имеет значение 2 2 2.
{ 2 2 2} выше относится на 22 2 и все его дети. Теперь, когда в дереве есть обратная ссылка на 4 4 семантика> 4, обход продолжается.
1 1 1 печатается, поскольку у него нет левого дочернего элемента и curr
возвращается в 2 2 2, который был преобразован в 1 1 Правый дочерний элемент 1 в предыдущей итерации. На следующей итерации 22 2 имеет обоих потомков. Однако двойное условие цикла заставляет его останавливаться, когда он достигает самого себя; это признак того, что его левое поддерево уже было пройдено. Итак, он печатает себя и продолжает свое правое поддерево ( 3 3 3). 33 3 печатает себя , а curr
становится 3 3 3 и проходит тот же процесс проверки, что и 2 2 2 сделал. Он также понимает, что его левое поддерево было пройдено, и продолжает 4 4 аннотация> 4. Остальная часть дерева следует тому же шаблону.
Код
Вышеупомянутый алгоритм реализован в приведенном ниже коде:
- C ++
- C ++
- C ++
- Python
- Python
- Java
- Java
#include с использованием пространства имен std; struct Node {int data; struct Node * left_node; struct Node * right_node; }; void Morris (struct Node * root) {struct Node * curr, * prev; если (корень == NULL) возврат; curr = корень; while (curr! = NULL) {если (curr-> left_node == NULL) {cout data right_node; } else {/* Найти предыдущий (предыдущий) curr */prev = curr-> left_node; while (prev-> right_node! = NULL && prev-> right_node! = curr) prev = prev-> right_node; /* Сделать curr правым потомком своего предыдущего */if (prev-> right_node == NULL) {prev-> right_node = curr; curr = curr-> left_node; }/* исправляем правый дочерний элемент предыдущего */else {prev-> right_node = NULL; cout data right_node; }}}} struct Node * add_node (int data) {struct Node * node = новый узел; узел-> данные = данные; узел-> left_node = NULL; узел-> right_node = NULL; возврат (узел); } int main () {узел структуры * root = add_node (4); корень-> left_node = add_node (2); корень-> right_node = add_node (5); корень-> left_node-> left_node = add_node (1); корень-> left_node-> right_node = add_node (3); Моррис (корень); возврат 0; }