用Java排序数组

时间:2012-05-28 02:26:31

标签: java sorting

作为示例,我在java中开发了一个简单的MySortedSet,它实现了SortedSet接口。它备份有一个简单的数组,即E []数组。

我有几个问题:

这是班级:(我不是在编写整个代码,而是编写相关部分)

public class MySortedSet<E> implements SortedSet<E>, Iterator<E> {

 private E[] array;
 private Comparator<? super E> _comparator;
 private int size = 0;
 private int capacity;

 @SuppressWarnings("unchecked")
 public MySortedSet() {
    this.capacity = 10;
    this.array = (E[]) new Object[this.capacity];
    // this.array = Array.newInstance(Class<E> var,int size);
    // We have to get Class<E> from outside caller.
 }
}

问题3:有一个构造函数的解释,因为这是一个有序集,所以假设元素已经排序:

  

如果使用此构造函数创建有序集,则假定它   元素是按照它们的自然顺序排序的(即E   实现Comparable)。

它有两个不同的构造函数。一个是无参数的,另一个是接受Comparator<? super E>

public MySortedSet() {
    this.capacity = 10;
    this.array = (E[]) new Object[this.capacity];
    // this.array = Array.newInstance(Class<E> var,int size);
    // We have to get Class<E> from outside caller.
}

public MySortedSet(Comparator<? super E> comparator) {
    this._comparator = comparator;
}

如果未传入comparator,则应使用自然排序但我不确定如何完成,因为我需要以某种方式获取Comparator来访问compare方法。你们有没有给我推荐一种方法来调用它,所以我可以在用sort方法比较每个元素时调用它。

对于他们想要查看完整代码的人,请参阅此地址:http://codepaste.net/4ucvsw这不完美,但我正在努力。

问题4:代码指南说:

  

因为搜索特定项目的最快方法是使用a   二进制搜索,您必须确保集合中的项目在   始终按顺序排序。这不会像现在这样难以实现   似乎。插入新项目时,您可以假设您是阵列   插入已经排序。所以你需要做的就是找到   在新项目所属的数组中的位置,移动一切   大于新项目右侧的一个插槽,并插入新的   项目。这称为插入排序。

这是sort方法逻辑。我需要进行二分搜索以找到新项目所属的位置,以便我可以在该位置插入新项目并将另一个插槽向右移动。

但是我不确定二进制搜索在这里对我有用,因为我不确定我需要找到什么。我得到的项目不是要添加的项目。相反,我认为将每个元素与我需要添加的元素进行比较,当我找到最后一个较小且第一个较大的项目时,我将获得第一个更大项目的索引,将它们移动到右侧并在索引处添加新项目

2 个答案:

答案 0 :(得分:1)

回答3:

“自然排序”意味着元素必须实现Comparable,以便可以在不使用Comparator的情况下进行比较。让调用者在Comparable元素和Comparator之间做出选择的棘手部分是,您无法进行编译时检查以确保它们满足至少一个这些要求。

Java TreeSet同样公开了一个构造函数,它接受Comparator而其他构造函数不接受TreeSet。如果你没有为ClassCastException提供{Comparable,那么TreeSet的合同基本上会抛出一个Comparator。 {1}}当你创建它时。无论您是想要使用此策略还是其他策略都取决于您。

回答4:

根据报价的策略,您应该能够将Arrays.binarySearch(Object[], Object)用于此目的。从该方法的文档:

  

返回:搜索键的索引(如果它包含在数组中);   否则,(-(insertion point) - 1)。插入点定义为   密钥插入数组的点:索引   大于键的第一个元素的大小,或者a.length的所有元素   在数组中小于指定的键。请注意这一点   当且仅当密钥时,保证返回值>&gt; = 0   找到了。

答案 1 :(得分:1)

问题3:

事实是,每个集合都使用预定义的比较器,该比较器在E上隐式定义,因此用于具体化类型参数E的每个类都应该{{3} }。您正在寻找自然排序的比较方法是方法

int compareTo(E other)

必须由您将用于数据结构的类实现。由于您的工作与定义要与您的集合一起使用的类无关,而只与集合本身有关,您将要做什么

public class MySortedSet<E> ... {
    private Comparator<? super E> _comparator;

    public int innerCompare(E e1, E e2)
    {
      if (_comparator != null)
        return _comparator.compare(e1,e2);
      else
        return e1.compareTo(e2);
    }

    ...

因此,您将在提供时使用自定义比较器,否则使用自然比较器。

ComparableComparator都遵循相同的原则,但第一个,如名称所示,附加到数据类,因此它是它的自然比较器。相反,使用后者是因为它允许您定义一种自定义方式来排序元素,这些元素将根据自然顺序以不同的方式排序。

问题4:

这意味着,在拥有排序数组的假设下,您必须在每次插入后保持此约束有效,并且在查找项目时您将被允许进行二进制搜索。

您必须专注于将元素放置在正确的索引处(您必须添加的项目)。与查找元素相关的语句部分必须按以下方式解释:

  

如果你负责保持你的数组排序,可以通过确保你添加的每个元素都放在正确的位置(例如插入排序)来完成,那么你可以在查看元素时对数组应用二进制搜索包含在集合中。

这是正确的,因为如果对数组进行排序,您可以确保查看数组的某个部分的中间元素将始终指向正确的方向,以查看列表中是否确实包含另一个元素。

EG:

1, 2, 6, 11, 21, 30, 45

您需要检查2,您可以在索引size()/2 = 3处获取元素,即11。既然您已经知道数组已经排序并且2 < 11您可以在左半部分递归地执行相同的操作,依此类推。