我有一个预先订购的节点列表,我需要转回树。我对结果树有一些保证。
我确信只要上述两个约束成立,就可以创建一个树。
预订节点列表的示例可能是:
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甚至伪代码中的提示或解决方案。
答案 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个子节点。