作为示例,我在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
方法逻辑。我需要进行二分搜索以找到新项目所属的位置,以便我可以在该位置插入新项目并将另一个插槽向右移动。
但是我不确定二进制搜索在这里对我有用,因为我不确定我需要找到什么。我得到的项目不是要添加的项目。相反,我认为将每个元素与我需要添加的元素进行比较,当我找到最后一个较小且第一个较大的项目时,我将获得第一个更大项目的索引,将它们移动到右侧并在索引处添加新项目
答案 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);
}
...
因此,您将在提供时使用自定义比较器,否则使用自然比较器。
Comparable
和Comparator
都遵循相同的原则,但第一个,如名称所示,附加到数据类,因此它是它的自然比较器。相反,使用后者是因为它允许您定义一种自定义方式来排序元素,这些元素将根据自然顺序以不同的方式排序。
问题4:
这意味着,在拥有排序数组的假设下,您必须在每次插入后保持此约束有效,并且在查找项目时您将被允许进行二进制搜索。
您必须专注于将元素放置在正确的索引处(您必须添加的项目)。与查找元素相关的语句部分必须按以下方式解释:
如果你负责保持你的数组排序,可以通过确保你添加的每个元素都放在正确的位置(例如插入排序)来完成,那么你可以在查看元素时对数组应用二进制搜索包含在集合中。
这是正确的,因为如果对数组进行排序,您可以确保查看数组的某个部分的中间元素将始终指向正确的方向,以查看列表中是否确实包含另一个元素。
EG:
1, 2, 6, 11, 21, 30, 45
您需要检查2,您可以在索引size()/2 = 3
处获取元素,即11
。既然您已经知道数组已经排序并且2 < 11
您可以在左半部分递归地执行相同的操作,依此类推。