【问题标题】:sort Array before adding to a Binary Search tree Java在添加到二叉搜索树 Java 之前对数组进行排序
【发布时间】:2011-12-23 11:15:30
【问题描述】:

我有一个按 A-Z 顺序排列的字符串数组。我想知道对它们进行排序以获得平衡二叉搜索树的最佳方法。我最初的想法是将数组分成前半部分和后半部分,然后分别对它们进行排序。

我不应该能够使用递归方式将其分成两半以获得树的下一个节点吗?我现在无法理解它,并想我会问是否有人有任何想法。引导我走向正确的方向或提供一些例子。谢谢!

我正在使用我自己的 BinaryTree 类和 BinaryTreeNode 类。 编辑:

public class BinaryTree {
private BinaryTreeNode root;

public void insert(String text) {

root = insertNode(root, text); 

}

private BinaryTreeNode insertNode(BinaryTreeNode curNode, String text) {
if (curNode == null) {
    BinaryTreeNode newNode = new BinaryTreeNode(text);
    //newNode.value = text;
    return newNode;
} else {
    if (text.compareTo(curNode.value) < 0 ) {
        //left child
        //use of recursion to properly place Node
        curNode.left = insertNode(curNode.left, text);
        return curNode;
    }

        else {

        //right
        //use of recursion to properly place Node
        curNode.right = insertNode(curNode.right, text);
        return curNode;
    }
}

}

public BinaryTreeNode getRoot() {
return root;
}

 public void setRoot(BinaryTreeNode root) {
this.root = root;
 }
 }

这会被认为是自平衡二叉搜索树吗?

【问题讨论】:

    标签: java recursion binary-search-tree


    【解决方案1】:

    如果您有一个自平衡的二叉搜索树,那么对数组进行预排序很可能会适得其反。将排序数据优化添加到平衡树的算法与添加无序数据的算法有很大的不同。

    但是,您发布的代码没有任何“自我平衡”。就是一个普通的二叉树插入算法。

    【讨论】:

      【解决方案2】:

      你的树似乎没有自我平衡。 self-balancing BST 将在插入后或多次插入后采取措施,以确保(大致)平衡。

      如果您只添加一次元素并将树用于读取,则您拥有排序数组,然后按以下步骤操作:选择中间的元素。以它为键创建一个根,然后递归地将其左侧的元素(较小的元素)添加为根的左子树,并将其右侧的元素分别添加为右子树。你最终应该得到一个或多或少平衡的 BST。示例代码:

      public class BinaryTree {
      
          /* ... */
      
      
          //each recursive call receives a pair of bounds for the part of the 
          //array it has to process: left and right
          public static BinaryTreeNode nodeFromSortedArray(String[]a,
                                                 int left, int right){
      
              if (right<left) return null;
      
              if (right==left)
                  return new BinaryTreeNode(a[left]);
      
              int mid = (left+right)/2;
      
              //create node from middle element
              BinaryTreeNode n = new BinaryTreeNode(a[mid]);
      
              //recursively add elements to the left as its right subtree
              n.left = nodeFromSortedArray(a, left, mid-1);
      
              //recursively add elements to the right as its right subtree
              n.right = nodeFromSortedArray(a, mid+1, right);
      
              return n;
          }
      
          public static BinaryTree fromSortedArray(String[]a){
              BinaryTree bt = new BinaryTree();
              bt.setRoot(nodeFromSortedArray(a,0,a.length-1));
              return bt;
          }
      
          /* ... */
      }
      

      但是,在这种情况下,您可以简单地将元素保留在已排序的数组中,并使用二分搜索对其进行索引,而不是使用树。复杂度应该是一样的,O(logn),但是你需要更少的引用来存储整个东西,并且缓存性能应该更好。

      如果您需要一棵可变树,并希望使其高效,您可能需要使其自平衡,在这种情况下,您向其中添加元素的顺序并不重要。

      【讨论】:

      • 感谢弗拉德,当我从文件加载数组时,我真的不需要自平衡树。我明白你在说什么。选择数组的中间作为根。但是我对递归地通过左侧或右侧感到困惑。我是否需要继续除以 2 以继续在递归函数中为左侧添加正确的值?这是我唯一坚持的部分。我从例子中学习得最好。谢谢!
      • 谢谢,我需要更多地学习递归。通过您的示例,我现在理解得更好了。
      • 我很乐意提供帮助。递归确实是一种有价值的技术,我认为您将能够找到有关该主题的大量文档。您可以从Fibonacci sequence 之类的简单内容开始,虽然使用递归很慢,但可以帮助您理解。您甚至可以手动跟踪代码并找出调用和返回。
      • 嘿,弗拉德,我有一个简单的问题。在使用上述递归算法时,我注意到某些特定节点位于不正确的位置以进行搜索并显示为空。例如:如果根节点 = "mark" 并且它的左子节点 = "cat" 不知何故 "cat" 的右子节点是 "bull"。在我的查找算法中,我使用 CompareTo 方法来检查要找到的单词是否 > 0
      • 如果您向我展示您传递给fromSortedArray 的数组,我可以自己尝试并找出问题所在。
      猜你喜欢
      • 2020-07-19
      • 2018-10-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多