【问题标题】:How to return the doubly linked list and remove leaves of the tree?如何返回双向链表并删除树的​​叶子?
【发布时间】:2015-12-11 23:19:30
【问题描述】:

我正在处理类似 SPOJ 的任务。目标是在二叉树(不一定是 BST)中找到叶子,从树中删除它们并将它们作为一种双向链表返回,使用相同的结构 - TreeNode 并且没有额外的导入。例如,如果从树中删除节点 2、4 和 3,则函数返回列表的第一个非空元素:null 4 3 -> null。 TreeNode 有一个值和左右指针。

我使用递归并取消叶子以从树中删除它们并在列表中重新创建它们。为了保持将元素添加到列表末尾的效率,我将指针指向列表的最后一个元素。这产生了一个众所周知的问题,即更改传递给函数的对象。这是我的代码:

public TreeNode getLeaves(TreeNode root)
{
    if(root == null)
        return null;

    TreeNode start = new TreeNode(Integer.MIN_VALUE);
    TreeNode[] end = {start};
    getLeaves(root, start, end);
    return start;
}

private void getLeaves(TreeNode root, TreeNode start, TreeNode[] end)
{
    if(root == null)
        return;

    if(root.left == null && root.right == null)
    {
        addToList(root, start, end);
        root = null;
        return;
    }
    getLeaves(root.left, start, end);
    getLeaves(root.right, start, end);
}

private void addToList(TreeNode element, TreeNode start, TreeNode[] end)
{
    if(end[0].value != Integer.MIN_VALUE)
    {
        TreeNode t = new TreeNode (element.value);
        end[0].right = t;
        t.left = end[0];
        end[0] = t;
    }
    else
    {
        start.value = element.value;
    }
}

从树中删除叶子不起作用,但列表会正确返回。但是,将“start”TreeNode 的值设置为最小 int 值而不是使用 null 引用会使我感到困惑,使用数组也是如此。恕我直言,使用原子引用会使它更加混乱。我很确定有一种方法可以以更优雅的方式(并正确删除叶子),可能是通过更改分配开始和结束 TreeNodes 的方法。我觉得我的方法和/或对所有工作方式的理解有问题。你能帮我把它变成一段简洁的代码并解释我的坏处吗?

【问题讨论】:

    标签: java algorithm list recursion


    【解决方案1】:

    您的第二个GetLeaves 函数有错误。语句 root = null;局部变量 root 的值设置为 null,但其父级将保留对叶的引用。

    如果您将方法bool isLeaf() 添加到TreeNode,您将有更轻松的时间。我将您的代码修改为我认为可行的代码。

    private bool isLeaf()
    {
        // This method should be in TreeNode
        return left == null && right == null;
    }
    // Also, TreeNode should have an Add(TreeNode) method
    
    public TreeNode getLeaves(TreeNode root)
    {
        if( root == null )  // check if the whole tree is empty
            return null;  // return something relevant here
        else if( root.isLeaf() )
            return root;  //cannot remove this leaf, unfortunately
        TreeNode leaves = new TreeNode()
        getLeaves(root, leaves);
        return leaves;
    }
    private void getLeaves(TreeNode current, TreeNode leaves)
    {
        // current is guaranteed to be non-null and not a leaf itself.
        if( current.left.isLeaf() ) {
            leaves.add(current.left);
            current.left = null;
        } else {
            getLeaves(current.left, leaves);
        }
        if( current.right.isLeaf() ) {
            leaves.add(current.right);
            current.right = null;
        } else {
            getLeaves(current.right, leaves);
        }
    }
    

    【讨论】:

      【解决方案2】:

      大卫,你是 100% 正确的。感谢您的帮助。如果有人想知道,这是迄今为止我制作的最优雅的解决方案,包括 David 的改进。我唯一不确定的是 addToList 方法是否应该是静态的,或者在元素的上下文中调用它是否更合适/更通用。

      public TreeNode getLeaves(TreeNode root)
      {
          if(root == null)
              return null;
      
          if(root.isLeaf())
              return root;
      
          TreeNode[] listEdges = {null, null};
          getLeaves(root, listEdges);
          return listEdges[0];
      }
      
      private void getLeaves(TreeNode root, TreeNode[] edges)
      {
          if(root == null)
              return;
      
          if(root.left != null && root.left.isLeaf())
          {
              addToList(edges, root.left);
              root.left = null;
          }
      
          if(root.right != null && root.right.isLeaf())
          {
              addToList(edges, root.right);
              root.right = null;
          }
          getLeaves(root.left, edges);
          getLeaves(root.right, edges);
      }
      
      private static void addToList(TreeNode[] edges, TreeNode element)
      {
          if(edges[1] != null)
          {
              edges[1].right = element;
              element.left = edges[1];
              edges[1] = element;
          }
          else
          {
              edges[0] = element;
              edges[1] = edges[0];
          }
      }
      
      public boolean isLeaf()
      {
          return this.right == null && this.left == null;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多