将预订中的节点列表转换回二叉树

时间:2018-06-04 06:41:09

标签: tree language-agnostic binary-tree preorder

我有一个预先订购的节点列表,我需要转回树。我对结果树有一些保证。

  • 这是full binary tree,意味着每个节点都有0或2个孩子。
  • 节点是否为叶子或分支包含在预订单列表中。

我确信只要上述两个约束成立,就可以创建一个树。

预订节点列表的示例可能是:

Branch(1), Branch(2), Leaf(3), Branch(4), Leaf(5), Leaf(6), Branch(7)

结果树:

       1
     /   \
   2       7
  / \
 3   4
    / \
   5   6

我无法想到可以从上述预订单列表中构建的其他树。

我尝试了一些不同的方法(主要是堆栈和队列),但是我花了最后几个小时才开始工作,但我还没有能够得到任何工作。

我更喜欢Rust中的解决方案,但我们会欣赏C,C ++,Python,Java甚至伪代码中的提示或解决方案。

2 个答案:

答案 0 :(得分:1)

当且仅当树是二叉搜索树时,您可以使用前序遍历来恢复二叉树。简单地说,您按照与遍历相同的顺序插入节点。

但是如果你的树不是二叉搜索树,那么你需要在遍历中放置外部节点(空指针)。有些人喜欢这样:

void preorder(Node * root)
{
  if (root == Node::NullPtr)
    {
      cout << "NULL ";
      return;
    }

  cout << root->key << " ";
  preorder(root->left);
  preorder(root->right);
}

让我们假设您在vector<string>对象中进行了前序遍历,然后为了获得原始树,您可以这样做:

Node * restore(const vector<string> & a, int & i)
{
  string key = a[i++];
  if (key == "NULL")
    return Node::NullPtr;

  Node * p = new Node;
  p->key = key;
  p->left = preorder(a, i);
  p->right = preorder(a, i);

  return p;
}

官方界面如下:

Node * restore(const vector<string> & a)
{
  int i = 0;
  return restore(a, i)
}

答案 1 :(得分:1)

在给它一些时间后,我已经为我的问题创建了一个解决方案。

基本上你有一个变量来保存你正在处理的当前节点,从root开始。遇到分支时,将分支添加到当前节点的子节点,然后将当前节点设置为该分支。遇到叶子时,将叶子添加到当前节点的子节点。您可以在while循环中执行此操作,直到列表为空。在每次循环迭代开始时,检查当前节点的子节点是否= = 2,如果是,则使节点指向它的父节点并继续这样做,直到当前节点变量指向具有&lt; 2个孩子。

这是我的条纹下降Rust实现:

struct Node { /* ... */ }
impl Node { /* ... */ }

enum NodeType {
    Branch(i32),
    Leaf(i32),
}

impl NodeType { /* ... */ }

fn list_to_tree(list: &[NodeType]) -> Node {
    let mut iter = list.iter();
    let root = Node::new(iter.next().unwrap().get_data());
    let mut node = &root;

    while let Some(next) = iter.next() {
        while node.child_count() == 2 {
            node = node.parent_ref();
        }

        match next {
            NodeType::Branch(data) => {
                node.add_child(Node::new(data));
                node = next;
            }
            NodeType::Leaf(data) => {
                node.add_child(Node::new(data));
            }
        }
    }

    root
}

它假定给出了一个非空列表,并且该列表是一个正确的预订单列表,该列表由一棵树组成,每个节点只有0或2个子节点。