【问题标题】:How to convert a Ternary expression to a Binary tree structure?如何将三元表达式转换为二叉树结构?
【发布时间】:2015-02-12 21:10:46
【问题描述】:

我遇到了这个问题,它具有三元表达式 (a?b:c),需要将三元表达式转换为二叉树结构。

     a?b:c 

       a
      / \
     b   c

  a?b?c:d:e

     a
    / \
   b   e
  / \
 c   d

我使用使用数组实现的二叉树的方法:-

父母居住在 -i 左孩子 - 2i 右孩子 - 2i+1

开始解析三元表达式,第一个字符将形成根节点,因此它将位于数组中的位置 1。如果下一个字符是“?”那么后面的字符将是它的孩子,所以左孩子(在这种情况下,b 将位于位置 2)。如果下一个字符是“:”,那么我们找到了正确的孩子(第一种情况下是 c),所以我们将其添加到位置 3。

在第二种情况下,我们面临一个“?”在 b 之后,因此后面的任何内容都将是它的子节点,并将分别添加到 2j 和 2j+1 中,其中 j 是 b 在数组中的位置。现在我们面对一个“:”,我们检查当前子节点的父节点是否有两个然后我们回溯并检查前一个节点,直到找到缺少右孩子的节点。

还有其他方法可以做到这一点吗?希望我已经足够清晰了。

【问题讨论】:

    标签: binary-tree ternary-operator data-conversion


    【解决方案1】:

    以下是我经过彻底测试的解决方案。

    class TreeNode {
        char c;
        TreeNode left;
        TreeNode right;
    
        TreeNode(char c) {
            this.c = c;
            left = null;
            right = null;
        }
    }
    
    public TreeNode tenaryToTree(String s) {
        if (s.length() == 0)
            return null;
    
        TreeNode root = new TreeNode(s.charAt(0));
        Stack<TreeNode> stack = new Stack<>();
        stack.push(root);
    
        for (int i = 1; i < s.length(); i++) {
            if (s.charAt(i) == '?') {
                TreeNode node = stack.peek();
                node.left = new TreeNode(s.charAt(i + 1));
                stack.push(node.left);
            } else if (s.charAt(i) == ':') {
                stack.pop();
                TreeNode node = stack.pop();
                node.right = new TreeNode(s.charAt(i + 1));
                stack.push(node.right);
            }
        }
    
        return root;
    }
    

    【讨论】:

      【解决方案2】:

      这一个将不使用父节点。但是使用堆栈。

          public NodeC convertTtoBT (char[] values) {
          char xx = values[0];
          NodeC n = new NodeC(xx);
          Stack<NodeC> a =  new Stack<NodeC>();
          for (int i = 1; i < values.length; i += 2) {
              if (values[i] == '?') {
                  n.left = new NodeC (values[i + 1]);
                  a.add(n);
                  n = n.left;
      
              }
              else if (values[i] == ':') {
                  n = a.pop();
                  while (n.right != null) {
                      n = a.pop();
                  }             
                  n.right = new NodeC (values[i + 1]);
                  a.add(n);
                  n = n.right;
              }
          }
          return n;
      }
      

      【讨论】:

      • 我认为如果你保存对树根的引用并返回它,它可能会更好。只需在第 3 行之后添加:NodeC root_node = n 并在最后,而不是“return n;”,您可以使用“return root_node”
      • 时间复杂度是O(n)吗?
      • 错误的解决方案。
      【解决方案3】:

      我用树想出了这样的东西。未彻底测试:

      当我看到一个“?”时,它是我的左孩子,所以添加到我的左边然后向左走。

      如果我看到':',那么:

      1. 去找我的父母
      2. 如果 right 不为 null 且 parent 不为 null,请继续找我的父母
      3. 我的右孩子是空的。加对。向右走。

      注意:如果它有一个正确的孩子,你永远不会回到根。

          public NodeC convertTtoBT (char[] values) {
          NodeC n = new NodeC (values[0]);
      
          for (int i = 1; i < values.length; i += 2) {
              if (values[i] == '?') {
                  n.left = new NodeC (values[i + 1]);
                  n = n.left;
              }
              else if (values[i] == ':') {
                  n = n.parent;
                  while (n.right != null && n.parent != null ) {
                      n = n.parent;
                  }                    
                  n.right = new NodeC (values[i + 1]);
                  n = n.right;
              }
          }
          return n;
      

      【讨论】:

        【解决方案4】:

        想法是从左到右开始解析字符串,当您遇到'?' 时,您将在树中更深入,否则只需返回创建的新节点。

        这是我的递归解决方案:

          struct node{
            char val;
            node *left;
            node *right;
            node(char v):val(v),left(NULL),right(NULL){
            }
        };
        
            node* create_tree(string input, int &current){
            if(current>=(int)input.size()){
                return NULL;
            }
            node *temp = new node(input[current]);
            current+=2;
            if(current<(int)input.size()){
                if(input[current-1]=='?'){
                    temp->left=create_ternary_tree(input,current);
                    temp->right=create_ternary_tree(input,current);
                }
            }
            return temp;
        }
        

        【讨论】:

        • 它会正确添加正确的树吗?我不这么认为
        【解决方案5】:

        我的解决方案: 每个树节点都没有父链接,所以我使用堆栈来保留它们。 这种解决方案的优点是我只将 root 推入堆栈,因此在 (if x==':' {}) 语句中,没有 while 循环,没有 push 语句。

            public  static TreeNode convert(String ternary) {
            char[] chs = ternary.toCharArray();
            Stack<TreeNode> stack = new Stack<TreeNode>();
            TreeNode cur=new TreeNode(chs[0]);
            TreeNode root= cur;
            for (int i=1; i<chs.length; i+=2) {
                if (chs[i]=='?') {
                    stack.push(cur);
                    TreeNode node = new TreeNode(chs[i+1]);
                    cur.left = node;
                    cur = node;
                }
                else if (chs[i]==':') {
                    cur = stack.pop();
                    TreeNode node = new TreeNode(chs[i+1]);
                    cur.right = node;
                    cur = node;
        
                }
            }
            return root;
        }
        

        【讨论】:

          【解决方案6】:

          从右到左遍历表达式,将任何字母作为节点推入堆栈。如果你看到“?”,那么不要压入下一个字母,而是将其作为根,从堆栈中弹出最后两个节点作为左右根的子节点,然后将根推回堆栈。

          public TreeNode ternaryToTree(char[] exp) {
              LinkedList<TreeNode> stack = new LinkedList<TreeNode>();
          
              for (int i = exp.length-1; i >= 0; i--) {
                  if (exp[i] == ':') continue;
                  if (exp[i] == '?') {
                      TreeNode node = new TreeNode(exp[--i]);
                      node.left = stack.pop();
                      node.right = stack.pop();
                      stack.push(node);
                  } else {
                      stack.push(new TreeNode(exp[i]));
                  }
              }
          
              return stack.isEmpty() ? null : stack.pop();
          }
          

          【讨论】:

            【解决方案7】:

            如果这个 a?b:c?d?e:f:g?h:i?j:k 是三元表达式,那么树会是这样的

                      a
                     / \
                    b   c
                       /  \
                      d    g
                     / \  / \
                    e   f h  i
                            / \
                           j   k
            

            下面是Java解决方案...

            private static TreeNode convertTernaryExpression(String s) 
            {
            
                Stack<TreeNode> stack = new Stack<>();
            
                int length = s.length();
                int index = 0;
                TreeNode rootNode = null;
                while(index < length)
                {
                    while(s.charAt(index) != ':')
                    {
                        if(s.charAt(index) == '?' && stack.peek().right != null)
                        {
                            TreeNode temp = stack.pop();
                            if(rootNode == null)
                            {
                                rootNode = temp;
                            }
                            stack.push(temp.right);
                        }
                        stack.push(new TreeNode(s.charAt(index++)));
                    }
            
                    TreeNode left = stack.pop();
                    TreeNode questionMark = stack.pop();
                    TreeNode root = stack.pop();
                    index++;
                    TreeNode right = new TreeNode(s.charAt(index++));
            
                    root.left = left;
                    root.right = right;
            
                    stack.push(root);
                }
            
                if(rootNode == null)
                {
                    return stack.pop();
                }
                else
                {
                    return rootNode;
                }
            }
            
            class TreeNode
            {
                TreeNode left;
                TreeNode right;
                char val;
                public TreeNode(char val) 
                {
                    this.val = val;
                    this.left = null;
                    this.right = null;
                }
            }
            

            【讨论】:

              【解决方案8】:
               public static TreeNode convert_loop(char[] expr) {
                  if (expr == null || expr.length < 1) {
                      return null;
                  }
                  if (expr.length == 1) {
                      return new TreeNode(expr[0]);
                  }
                  if ((expr.length - 1) % 4 != 0) {
                      throw new InputMismatchException("wrong expression");
                  }
                  int start = 0, end = expr.length - 1;
              
                  TreeNode<Character> root = new TreeNode<>(expr[start]);
                  root.right = new TreeNode<>(expr[end]);
              
                  start += 2;
                  end -= 2;
                  TreeNode<Character> cur = root;
              
                  while (start != end) {
                      TreeNode<Character> node = new TreeNode<>(expr[start]);
                      node.right = new TreeNode<>(expr[end]);
              
                      cur.left = node;
                      cur = node;
              
                      start += 2;
                      end -= 2;
                  }
                  cur.left = new TreeNode(expr[start]);// care
                  return root;
              }
              

              【讨论】:

                猜你喜欢
                • 2018-01-29
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2015-09-24
                • 1970-01-01
                • 2015-11-09
                • 2011-12-09
                • 1970-01-01
                相关资源
                最近更新 更多