Изучение обхода Морриса: эффективный алгоритм обхода дерева

В мире информатики алгоритмы обхода дерева играют решающую роль в эффективном доступе к элементам двоичного дерева. Одним из таких алгоритмов, который выделяется своей простотой и эффективностью, является обход Морриса. В этой статье мы углубимся в детали обхода Морриса, рассмотрим его различные реализации и предоставим примеры кода для каждого метода.

Что такое обход Морриса?
Обход Морриса — это алгоритм обхода дерева, который позволяет нам перемещаться по двоичному дереву без использования каких-либо дополнительных структур данных, таких как стеки или очереди. Это достигается путем временного изменения структуры дерева. Этот алгоритм в основном используется для обхода дерева по порядку, но его также можно адаптировать для обхода в предварительном и послепорядковом порядке.

Метод 1: обход по порядку Морриса
Первый метод, который мы рассмотрим, — это обход по порядку Морриса. Этот метод позволяет нам посещать узлы бинарного дерева в порядке возрастания.

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right
def morris_inorder(root):
    current = root
    while current:
        if not current.left:
            print(current.val)
            current = current.right
        else:
            predecessor = current.left
            while predecessor.right and predecessor.right != current:
                predecessor = predecessor.right
            if not predecessor.right:
                predecessor.right = current
                current = current.left
            else:
                predecessor.right = None
                print(current.val)
                current = current.right
# Usage example
root = TreeNode(4)
root.left = TreeNode(2)
root.right = TreeNode(6)
root.left.left = TreeNode(1)
root.left.right = TreeNode(3)
root.right.left = TreeNode(5)
root.right.right = TreeNode(7)
morris_inorder(root)

Метод 2: обход предварительного заказа Морриса
Второй метод, который мы рассмотрим, — это обход предварительного заказа Морриса. Этот метод позволяет нам посещать узлы бинарного дерева в предварительной последовательности.

def morris_preorder(root):
    current = root
    while current:
        if not current.left:
            print(current.val)
            current = current.right
        else:
            predecessor = current.left
            while predecessor.right and predecessor.right != current:
                predecessor = predecessor.right
            if not predecessor.right:
                predecessor.right = current
                print(current.val)
                current = current.left
            else:
                predecessor.right = None
                current = current.right
# Usage example (using the same tree as before)
morris_preorder(root)

Метод 3: обход постпорядка Морриса
Третий метод, который мы рассмотрим, — это обход постпорядка Морриса. Этот метод позволяет нам посещать узлы бинарного дерева в пост-порядке.

def reverse_nodes(start, end):
    if start == end:
        return
    prev = None
    current = start
    while prev != end:
        next_node = current.right
        current.right = prev
        prev = current
        current = next_node
def print_reverse(start, end):
    reverse_nodes(start, end)
    current = end
    while current != start:
        print(current.val)
        current = current.right
    reverse_nodes(end, start)
def morris_postorder(root):
    dummy = TreeNode(0)
    dummy.left = root
    current = dummy
    while current:
        if not current.left:
            current = current.right
        else:
            predecessor = current.left
            while predecessor.right and predecessor.right != current:
                predecessor = predecessor.right
            if not predecessor.right:
                predecessor.right = current
                current = current.left
            else:
                print_reverse(current.left, predecessor)
                predecessor.right = None
                current = current.right
# Usage example (using the same tree as before)
morris_postorder(root)

Morris Traversal обеспечивает эффективный способ обхода двоичных деревьев без использования дополнительных структур данных. Мы исследовали три метода: обход по порядку Морриса, обход по предварительному заказу Морриса и обход по посту Морриса, каждый из которых имеет свой собственный пример кода. Используя уникальные свойства обхода Морриса, мы можем оптимизировать обход деревьев и повысить эффективность наших алгоритмов.

Включение обхода Морриса в ваши древовидные решения может изменить правила игры, предлагая улучшенную временную и пространственную сложность по сравнению с традиционными методами обхода. Так почему бы не попробовать и не ощутить преимущества на собственном опыте?

Не забывайте экспериментировать с различными древовидными структурами и изучать другие варианты обхода Морриса, чтобы глубже понять этот мощный алгоритм.