Учитывая двоичное дерево с резьбой по порядку и узел, как найти родителя этого конкретного узла?

#algorithm #tree #binary-tree #inorder #postorder

Вопрос:

Изображение по ссылке ниже является примером ДВОИЧНОГО ДЕРЕВА С ПОТОКАМИ ПО ПОРЯДКУ

Нам дается двоичное дерево с упорядоченными потоками. Это означает, что если у узла нет левого дочернего элемента (правого дочернего элемента), левые потоки (правые потоки) связаны с этим узлом с его предшественником по порядку (преемником по порядку).

Можете ли вы помочь мне придумать псевдокод или алгоритм, который нашел бы родителя узла? Например (см. фото ниже), данный узел-Q, родителем должен быть I. (Предполагается, что мы должны использовать данную идею о том, что двоичный файл упорядочен по потоку)

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

Комментарии:

1. Почему Q. слева указывает на головной узел? В вашем тексте говорится, что он будет указывать на предшественника Q, но головной узел не является предшественником Q.

2. Что такое 0 и 1 на картинке? Есть ли у ваших узлов такие свойства?

3. @trincot поскольку у крайнего левого узла нет предшественника по порядку, а у крайнего правого узла нет преемника по порядку, оба узла будут указывать на головной узел. ОБХОД ПО ПОРЯДКУ: Q U I C K S O R T

4. @тринкот Да. Крайнее левое свойство называется LTAG, а крайнее правое-RTAG. В принципе, LTAG (RTAG) равен 1, если у него есть левый дочерний элемент (правый дочерний элемент). В противном случае значение равно 0.

Ответ №1:

Судя по картинке, кажется, что:

  • head узел-это специальный сторожевой узел, который просто служит сторожевым узлом для прикрепления фактического дерева (которое может быть пустым).
  • узлы имеют два дополнительных логических флага, указывающих, есть ли у них левый/правый дочерний элемент

Тогда логика поиска родителя данного узла может быть следующей:

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

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

 class Node {
    constructor(value=null, left=null, right=null) {
        this.value = value;
        this.hasLeft = false;
        this.hasRight = false;
        this.left = left || this; // Default is self-reference
        this.right = right || this; // Default is self-reference
    }
    insertLeft(value) {
        this.hasLeft = true;
        this.left = new Node(value, this.left, this);
        return this.left;
    }
    insertRight(value) {
        this.hasRight = true;
        this.right = new Node(value, this, this.right);
        return this.right;
    }
    parent() {
        // Find rightmost node of subtree
        let node = this;
        while (node.hasRight) {
            node = node.right;
        }
        node = node.right; // go to ancestor
        // The this-node is in the left subtree of node.
        if (node.left === this) return node;
        node = node.left;
        while (node.right !== this) {
            node = node.right;
        }
        return node;
    }
    * inorder() {
        if (this.hasLeft) yield * this.left.inorder();
        if (this.right !== this) yield this; // When it is not the head
        if (this.hasRight) yield * this.right.inorder();
    }
}

// Create the example tree:
let head = new Node(); // Sentinel node (without data)
head.insertLeft("C").insertLeft("I").insertLeft("Q").insertRight("U").right.right
                    .insertRight("S").insertLeft("K").right
                                     .insertRight("R").insertLeft("O").right
                                                      .insertRight("T");

// Visit each node, display its value and that of its parent:
for (let node of head.inorder()) {
    console.log("parent of "   node.value   " is "   node.parent().value);
} 

Комментарии:

1. большое спасибо за это! 🙂