将特定类型的字符串转换为二叉树

问题描述

我们有一个这种格式的输入字符串"(1(2(4)(5))(3(6(8)(9))(7)))"
我们必须构建一个二叉树,使得 1 是根节点,第一个完整的括号包含 (2(4)(5)) 包含 1 的左孩子的家族
(3(6(8)(9))(7)) 是根 A 的右孩子的家庭。
最后,树看起来像这样。
Like this


我找不到编写转换这个算法的确切算法。提前致谢!

解决方法

当然,我不能在这里只为您的作业编写代码 :-) 但我认为如果您将每个符号视为一个操作,例如

( = down
1 = add
( = down
2 = add
( = down 
4 = add
) = up (goes to level of 2)
( = down
5 = add
) = up (goes to level of 2)
) = up (goes to level of 1)
( = down
3 = add
( = down
6 = add
( = down
8 = add
) = up (goes to level of 6)
( = down
9 = add
) = up (goes to level of 6)
) = up (goes to level of 3)
( = down
7 = add
) = up (goes to level of 3)
) = up (goes to level of 1)
) = up (leaves)

如果您从递归算法的角度考虑,您可能会将“下降”视为递归方法调用,将“上升”视为从递归方法调用返回(自动发生,然后方法本身完成)。

我强烈建议你尝试解决问题,因为学习真的很重要。

但是,如果您仍然找不到解决方案,您可以在此处找到有关如何解决它的详细说明。 https://www.geeksforgeeks.org/construct-binary-tree-string-bracket-representation/

,

想想堆栈。 当你看到一个“(”将元素压入堆栈,当你看到一个“)”时弹出堆栈,但将其作为子元素分配给堆栈的顶部元素。

让我们来看看例子"( 1 ( 2 ( 4 ) ( 5 ) ) ( 3 ( 6 ( 8 ) ( 9 ) ) ( 7 ) ) )"

  • (1 -> 推 1

  • (2 -> 推 2

  • (4 -> 推 4

  • ) -> 弹出 4,但将 4 作为子节点分配到堆栈顶部,即 2(查看左子是否可用然后分配为左子子否则为右子子)

当前树:

enter image description here

  • (5 -> 推 5
  • ) -> pop 5,栈顶仍然是 2 ( left 不可用所以将其指定为 2 的右孩子)

当前树:

enter image description here

  • ) -> 弹出 2,栈顶为 1(左边 1 可用,因此分配 2 作为 1 的左子节点)

当前树:

enter image description here

  • (3 -> 推 3

  • (6 -> 推 6

  • (8 -> 推 8

  • ) -> 弹出 8,栈顶 6 的左边可用 将 8 分配给 6 的左边

当前树:

enter image description here

  • (9 -> 推 9

  • ) -> pop 9 -> 将其添加到栈顶的右孩子,即 6 的右孩子,因为 6 的左被视为 8。

当前树:

enter image description here

  • ) -> pop 6 -> 将其添加到堆栈顶部,即 3 的左子节点可用。

当前树:

enter image description here

  • (7 -> 推 7

  • ) -> pop 7 -> 将其添加到栈顶,即 3 的右孩子,因为 3 的左孩子被视为 6。

enter image description here

  • ) -> pop 3 -> 将其添加到栈顶,即 1 的右孩子,因为 1 的左孩子被视为 2。

当前树:

enter image description here

  • ) -> pop 1 -> 现在堆栈中没有任何内容。完成。

在 Java 中使用堆栈实现的完整可运行示例是:

import java.util.*;
public class Main
{
    public static void main(String[] args) {
        TreeNode root = buildTree("(1(2(4)(5))(3(6(8)(9))(7)))");
        levelOrder(root);
    }
    
    static class TreeNode {
        int val;
        TreeNode left,right;
        public TreeNode(int val) {
            this.val = val;
        }
    }
    
    private static TreeNode buildTree(String s) {
        Deque<TreeNode> dq = new ArrayDeque<>();
        TreeNode rootNode = null;
        for ( int i = 0; i < s.length(); i++ ) {
            if ( s.charAt(i) == '(' ) {
                Integer current = Integer.parseInt(String.valueOf(s.charAt(i+1)));
                dq.push(new TreeNode(current));
            } else if ( s.charAt(i) == ')' ) {
                TreeNode node = dq.pop();
                if ( dq.isEmpty() ) {
                    break;
                } else {
                    
                    rootNode = dq.peek();
                    if (rootNode.left == null) {
                        rootNode.left = node;
                    } else {
                        rootNode.right = node;
                    }
                }
            }
        }
        return rootNode;
    }
    
    private static void levelOrder(TreeNode root) {
        Deque<TreeNode> dq = new ArrayDeque<>();
        dq.offer(root);
        while(!dq.isEmpty()) {
            int sz = dq.size();
            
            for ( int i = 0; i < sz; i++ ) {
                TreeNode node = dq.poll();
                System.out.print(node.val + " ");
                if ( node.left != null ) {
                    dq.offer(node.left);
                }
                if ( node.right != null ) {
                    dq.offer(node.right);
                }
            }
            System.out.println();
        }
        
    }

}
,

该字符串按预序列出节点。因此,递归解决方案将是一个可能的选择。

在 JavaScript 中,你可以这样写:

class Node {
    constructor(value) {
        this.value = value;
        this.children = [];
    }
}

function createTree(str) {
    // Extract numbers and parentheses from input into an array
    let tokens = str.match(/\d+|./g);
    if (!tokens) return null;
    let i = 1; // skip first character,as it must be a "("
    
    function recur() {
        let node = new Node(tokens[i++]);
        while (tokens[i++] != ")") {
            node.children.push(recur());
        }
        return node;
    }
    
    return recur();
}

// Demo run
let str = "(1(2(4)(5))(3(6(8)(9))(7)))";
let tree = createTree(str);
// Output the tree in JSON format
console.log(JSON.stringify(tree,null,2));

请注意,此实现不会对输入执行任何验证。假设输入的语法正确。

该算法将接受非二叉树的编码,因为这种格式可以编码具有任意数量子节点的节点。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...