Обход дерева порядка: какое определение правильное?

У меня есть следующий текст из академического курса, который я недавно изучил, о обходе порядка (они также называют это панкейкингом) двоичного дерева (не BST):

Обход дерева в порядке

Проведите линию вокруг дерева с внешней стороны. Начните слева от корня и обойдите дерево снаружи, чтобы закончить справа от корня. Держитесь как можно ближе к дереву, но не переходите его. (Думайте о дереве - его ветвях и узлах - как о твердом барьере.) Порядок узлов - это порядок, в котором эта линия проходит под ними. Если вы не уверены, когда вы идете «под» узлом, помните, что узел «слева» всегда идет первым.

Вот используемый пример (дерево немного отличается от приведенного ниже)

tree 1

Однако когда я выполняю поиск в Google, я получаю противоречивое определение. Например, пример википедии:

Определение дерева

Последовательность обхода в порядке: A, B, C, D, E, F, G, H, I (левый ребенок, корневой узел, правый узел)

Но согласно (моему пониманию) определения №1 это должно быть

A, B, D, C, E, F, G, I, H

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


person Chris S    schedule 28.01.2009    source источник
comment
Нет - согласно определению один, вы проходите под G, но вы проходите мимо I к H и под ним, а затем под I - так что алгоритмы согласуются.   -  person Jonathan Leffler    schedule 28.01.2009
comment
Взять простую концепцию и объяснить ее сложным для понимания образом - это так академично.   -  person erikkallen    schedule 03.03.2010


Ответы (14)


В моей неудачной попытке нарисовать вот порядок, который показывает, как их следует выбирать. alt text

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

person John Boker    schedule 28.01.2009
comment
Как это отвечает на вопрос? - person ForYourOwnGood; 28.01.2009
comment
@ForYourOwnGood: Правильно. - person Jonathan Leffler; 28.01.2009
comment
Это показывает, что определения совершенно не противоречат друг другу: они имеют одинаковый эффект. - person Tim; 28.01.2009
comment
Крис уже сказал, что проход был A, B, C, D, E, F, G, H, I, так что рисование этой последовательности дает ответ на его вопрос? Он уже знал это. - person ForYourOwnGood; 28.01.2009
comment
Крис прочитал первое определение неправильно, в частности, проходит ниже. У Криса BDCE, но вы сдаете C, а не D. Итак. кроме того, что красная линия на A не направлена ​​вниз (а линия под G является маргинальной :-), эта диаграмма все это объясняет, особенно. с приведенным выше комментарием. - person paxdiablo; 28.01.2009
comment
+1 за правильный ответ, хотя диаграмма меня тоже покорила :-). - person paxdiablo; 28.01.2009
comment
@ForYourOwnGood пример изображения, который дал академический текст, не имел такого количества узлов, поэтому я использовал его вместо правильного чтения текста (комментарий mweerden) - person Chris S; 28.01.2009
comment
где рисунок? - person alper; 26.12.2016

Забудьте об определениях, гораздо проще просто применить алгоритм:

void inOrderPrint(Node root)
{
  if (root.left != null) inOrderPrint(root.left);
  print(root.name);
  if (root.right != null) inOrderPrint(root.right);
}

Всего три строчки. Измените порядок для предварительного и последующего заказа.

person Andrew Coleson    schedule 28.01.2009

Если вы внимательно прочитаете, то увидите, что первое «определение» говорит о начале слева от корня и что порядок узлов определяется тем, когда вы переходите под. Таким образом, B не является первым узлом, поскольку вы проходите его слева по пути к A, затем сначала проходите под A, после чего вы поднимаетесь и проходите под B. Поэтому кажется, что оба определения дают одинаковый результат.

person mweerden    schedule 28.01.2009

Я лично нашел эту лекцию весьма полезной.

person c4il    schedule 05.07.2010

Оба определения дают одинаковый результат. Не дайте себя обмануть буквами в первом примере - посмотрите на числа вдоль пути. Во втором примере для обозначения пути используются буквы - возможно, именно это вас сбивает с толку.

Например, в вашем примерном порядке, показывающем, как вы думали, что второе дерево будет проходить с использованием алгоритма первого, вы помещаете «D» после «B», но не должны, потому что все еще есть левый дочерний узел D доступны (поэтому в первом элементе указано «порядок, в котором эта строка проходит под ними».

person Mark Brittingham    schedule 28.01.2009

это может быть поздно, но это может быть полезно для кого-то позже .. вам просто не нужно игнорировать фиктивные или нулевые узлы, например, у узла G есть левый нулевой узел .. учитывая, что этот нулевой узел сделает все в порядке ..

person Ahmad Ibrahem    schedule 22.12.2011

Правильный обход будет следующим: как можно дальше слева с листовыми узлами (не корневыми узлами)

Левый Корень Правый

A B NULL

C D E

Нуль F G

H I NULL

F - корень или левый, я не уверен

person Vishal S    schedule 19.05.2012

Я думаю, что первое двоичное дерево с корнем a - это двоичное дерево, которое неправильно построено.

Постарайтесь реализовать так, чтобы вся левая часть дерева была меньше корня, а вся правая часть дерева была больше или равнялась корню.

person Chester Ryan M. Pascua    schedule 04.08.2010

Но согласно (моему пониманию) определения №1 это должно быть

A, B, D, C, E, F, G, I, H

К сожалению, ваше понимание неверно.

Всякий раз, когда вы прибываете к узлу, вы должны спуститься к доступному левому узлу, прежде чем вы посмотрите на текущий узел, затем вы посмотрите на доступный правый узел. Когда вы выбирали D перед C, вы не спускались сначала к левому узлу.

person Calyth    schedule 28.01.2009

Привет, по-моему, как упоминалось в вики, правильная последовательность для обхода порядка - левый-корень-правый.

До A, B, C, D, E, F, я думаю, вы уже поняли. Теперь после корня F следующий узел - это G, который имеет не левый узел, а правый узел, так что согласно правилу (левый-корень-правый) его нуль-г-правый. Теперь I - правый узел G, но у меня есть левый узел, поэтому обход будет GHI. Это правильно.

Надеюсь это поможет.

person swaps    schedule 03.03.2010

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

Правильный обход будет следующим: как можно дальше влево с листовыми узлами (A), вернуться к родительскому узлу (B), двигаться вправо, но, поскольку у D есть дочерний элемент слева, вы снова двигаетесь вниз (C), снова вверх к родительскому элементу C (D), к правому дочернему элементу D (E), вернуться к корню (F), перейти к правому листу (G), перейти к листу G, но, поскольку у него есть левый лист, переместите туда (H) , вернитесь к родителю (I).

вышеупомянутый обход читает узел, когда он указан в скобках.

person Matt    schedule 18.05.2010

структура пакета данных;

public class BinaryTreeTraversal {

public static Node<Integer> node;

public static Node<Integer> sortedArrayToBST(int arr[], int start, int end) {
    if (start > end)
        return null;

    int mid = start + (end - start) / 2;
    Node<Integer> node = new Node<Integer>();
    node.setValue(arr[mid]);

    node.left = sortedArrayToBST(arr, start, mid - 1);
    node.right = sortedArrayToBST(arr, mid + 1, end);
    return node;
}

public static void main(String[] args) {

    int[] test = new int[] { 1, 2, 3, 4, 5, 6, 7 };
    Node<Integer> node = sortedArrayToBST(test, 0, test.length - 1);

    System.out.println("preOrderTraversal >> ");

    preOrderTraversal(node);

    System.out.println("");

    System.out.println("inOrderTraversal >> ");

    inOrderTraversal(node);

    System.out.println("");

    System.out.println("postOrderTraversal >> ");

    postOrderTraversal(node);

}

public static void preOrderTraversal(Node<Integer> node) {

    if (node != null) {

        System.out.print(" " + node.toString());
        preOrderTraversal(node.left);
        preOrderTraversal(node.right);
    }

}

public static void inOrderTraversal(Node<Integer> node) {

    if (node != null) {

        inOrderTraversal(node.left);
        System.out.print(" " + node.toString());
        inOrderTraversal(node.right);
    }

}

public static void postOrderTraversal(Node<Integer> node) {

    if (node != null) {

        postOrderTraversal(node.left);

        postOrderTraversal(node.right);

        System.out.print(" " + node.toString());
    }

}

}

структура пакета данных;

public class Node {

E value = null;
Node<E> left;
Node<E> right;

public E getValue() {
    return value;
}

public void setValue(E value) {
    this.value = value;
}

public Node<E> getLeft() {
    return left;
}

public void setLeft(Node<E> left) {
    this.left = left;
}

public Node<E> getRight() {
    return right;
}

public void setRight(Node<E> right) {
    this.right = right;
}

@Override
public String toString() {
    return " " +value;
}

}

preOrderTraversal >> 4 2 1 3 6 5 7 inOrderTraversal >> 1 2 3 4 5 6 7 postOrderTraversal >> 1 3 2 5 7 6 4

person Neel Salpe    schedule 23.01.2014
comment
out out is preOrderTraversal ›› 4 2 1 3 6 5 7 inOrderTraversal ›› 1 2 3 4 5 6 7 postOrderTraversal ›› 1 3 2 5 7 6 4 - person Neel Salpe; 23.01.2014

void
inorder (NODE root)
{
  if (root != NULL)
    {
      inorder (root->llink);
      printf ("%d\t", root->info);
      inorder (root->rlink);
    }
}

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

person Chandra Kanth    schedule 10.11.2015

Правильно для предзаказа, нет для inorder

person user3352445    schedule 25.02.2014