Двоичное дерево из обхода по предзаказу и по порядку - PullRequest
2 голосов
/ 11 апреля 2011

Как я могу получить дерево из этих предварительных / в порядке обхода:

Предварительно: A, B, D, E, C, F, G, H в: E, D, B, A, G, F, H, C

РЕДАКТИРОВАНИЕ: МОЙ Ответ

       A
      / \
     B   C
    /     \
   D       F
  /       / \
 E       G   H

Ответы [ 3 ]

2 голосов
/ 11 апреля 2011

EDIT: Коррекция,

У вас нет правильного ответа, FGH слева от C.

Для проверки просто запустите два алгоритма:

PreOrder(node)
  if node is null return
  Print(node)
  PreOrder(node.left)
  PreOrder(node.Right)

InOrder(node)
  if node is null return
  InOrder(node.left)
  Print(node)
  InOrder(node.Right)

Вы знаете, что A является корнем, потому что он запускает предварительный заказ. Используйте порядок, чтобы расположить узлы слева и справа от A. B - второй узел (предварительный порядок) и слева от A (по порядку) и т. Д.

Вы знаете, что F, G, H остались от C из-за упорядочения по порядку.

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

РЕДАКТИРОВАТЬ (18 апреля 2011 г.) :

Чтобы показать, насколько механичен процесс, я предлагаю этот псевдокод:

// Add method on binary tree class -- stock standard
method Add(item, comparer)
  newNode = new Node(item)
  parent = null

  // Find suitable parent
  currentNode = root
  while currentNode is not null
    parent = currentNode
    if comparer(newNode.Key, currentNode.Key) < 0
      currentNode = currentNode.Left
    else 
      currentNode = currentNode.Right

  // Add new node to parent
  if parent is null
    root = newNode
  else if comparer(newNode.Value, parent.Value) < 0 
    parent.Left = newNode
  else 
    parent.Right = newNode

Хитрость заключается в том, чтобы использовать последовательность по порядку, чтобы определить, добавлен ли узел слева или справа от его родителя, например:

// Client code
// Input arrays
var preOrder = ["A","B","D","E","C","F","G","H"]
var inOrder  = ["E","D","B","A","G","F","H","C"]
// A collection associating the Key value with its position in the inOrder array
var inOrderMap = GetInOrderMap(inOrder)

// Build tree from pre-order and in-order sequences
foreach (item in preOrder) 
  Add(item, fun (l, r) -> inOrderMap[l] - inOrderMap[r])

Я передаю лямбу, но любой эквивалентный метод для передачи компаратора должен подойти.

0 голосов
/ 24 ноября 2016

Вот математический подход к достижению вещи очень упрощенным способом:

Используемый язык: Java

`
/ * Алгоритм построения двоичного дерева по заданным обходам Inorder и Preorder. Ниже приводится используемая терминология:

i: представляет предоставленный массив заказов

p: представляет предоставленный массив предзаказа

beg1: начальный индекс массива inorder

beg2: начальный индекс массива предзаказа

end1: конечный индекс массива inorder

end2: конечный индекс массива предзаказа

* /

public static void constructTree (Node root, int [] i, int [] p, int beg1, int end1, int beg2, int end2)

{

if(beg1==end1 && beg2 == end2)
{
    root.data = i[beg1];
}
else if(beg1<=end1 && beg2<=end2)
{
    root.data = p[beg2];
    int mid = search(i, (int) root.data);
    root.left=new Node();
    root.right=new Node();
    constructTree(root.left, i, p, beg1, mid-1, beg2+1, beg2+mid-beg1);
    System.out.println("Printing root left : " + root.left.data);
    constructTree(root.right, i, p, mid+1, end1, beg2+1+mid-beg1, end2);
    System.out.println("Printing root left : " + root.right.data);
}

}

`

Вам нужно вызвать функцию с помощью следующего кода:

int[] i ={4,8,7,9,2,5,1,6,19,3,18,10}; //Inorder
int[] p ={1,2,4,7,8,9,5,3,6,19,10,18}; //Preorder
Node root1=new Node();
constructTree(root1, i, p, 0, i.length-1, 0, p.length-1);

Если вам нужно более подробное объяснение кода, пожалуйста, укажите это в комментариях. Я был бы рад помочь:).

0 голосов
/ 08 декабря 2012

Ниже приведена рабочая реализация на C #

public static class TreeUtil
{
   public static BinarySearchTree<T> FromTraversals<T>(T[] preorder, T[] inorder)
   {
       if (preorder == null) throw new ArgumentNullException("preorder");
       if (inorder == null) throw new ArgumentNullException("inorder");
       if (preorder.Length != inorder.Length) throw new ArgumentException("inorder and preorder have different lengths");

       int n = preorder.Length;
       return new BinarySearchTree<T>(FromTraversals(preorder, 0, n - 1, inorder, 0, n - 1));
   }

   public static BinaryTreeNode<T> FromTraversals<T>(T[] preorder, int pstart, int pend, T[] inorder, int istart, int iend)
   {
       if (pstart > pend) return null;

       T rootVal = preorder[pstart];
       int rootInPos;
       for (rootInPos = istart; rootInPos <= iend; rootInPos++) //find rootVal in inorder
           if (Comparer<T>.Default.Compare(inorder[rootInPos], rootVal) == 0) break;

       if (rootInPos > iend)
           throw new ArgumentException("invalid inorder and preorder inputs");

       int offset = rootInPos - istart;
       return new BinaryTreeNode<T>(rootVal)
           {
               Left = FromTraversals(preorder, pstart + 1, pstart + offset, inorder, istart, istart + offset - 1),
               Right = FromTraversals(preorder, pstart + offset + 1, pend, inorder, istart + offset + 1, iend),
           };
   }
}

Вот одна из возможных реализаций BinarySearchTree<T> и BinaryTreeNode<T>. Некоторые тесты:

[TestMethod]
public void TestGenerationFromTraversals()
{
  var preorder = new[] {1, 2, 4, 5, 3};
  var inorder = new[] {4, 2, 5, 1, 3};
  AssertGenerationFromTraversal(preorder, inorder);

  var preorder2 = new[] { 'A', 'B', 'D', 'E', 'C', 'F' };
  var inorder2 = new[] { 'D', 'B', 'E', 'A', 'F', 'C' };
  AssertGenerationFromTraversal(preorder2, inorder2);
}

private static void AssertGenerationFromTraversal<T>(T[] preorder, T[] inorder)
{
  var tree = BinarySearchTreeUtil.FromTraversals(preorder, inorder);

  var treeInorder = new List<T>();
  tree.TraverseInOrder(treeInorder.Add);
  var treePre = new List<T>();
  tree.TraversePreOrder(treePre.Add);

  Assert.IsTrue(preorder.SequenceEqual(treePre));
  Assert.IsTrue(inorder.SequenceEqual(treeInorder));
}
...