[英]Java: Sorting Elements
我知道我们通常使用java.util.Arrays.sort(Object[], Comparator)
。 JavaDoc 说它是一个修改过的归并排序。
但我需要一个排序算法,将每个 object 与每个 object 进行比较。 我会有很多顺序无关紧要的元素。 但是有些元素确实需要在特定的其他元素之后(不一定是连续的)。 而且我认为(但不知道)合并排序是不够的......
也许,我想要实现的甚至不叫排序?
我是否需要自己实现这样的系统,或者是否有为此而存在的东西?
例子:
Obj1, Obj2, Obj3, Obj4
以下情侣的顺序无关紧要(这意味着我的 Comparator 应该返回 0):
Obj1, Obj2 (*)
Obj1, Obj3
Obj2, Obj3
Obj2, Obj4 (*)
Obj3, Obj4
但! Obj4后面跟着Obj1确实很有必要。
由于有两个 (*) 对,这在数学上意味着 Obj1 == Obj4。
它可以使用归并排序吗?
谢谢
如果您知道理想的排序,一种选择是添加一些可排序的值,例如表示数据之间关系的 integer。 例如,如果项目 A 必须在项目 B 之前,则确保其排序值小于项目 B 的值。 然后,您可以提供一个仅查看排序值的自定义比较器,并且您可以使用标准排序算法。
听起来您有一组 DAG(有向无环图)。 我认为您需要对此进行 model ,然后对每个进行拓扑排序。 一种方法:
将每个元素包装在包装器 object 中,该包装器引用 object 并具有用于保存与其他对象的依赖关系的列表。 将所有这些包装器放入由 object id 键入的 hashMap 中。
对于没有直接依赖关系的所有元素,发出该元素,并将其从 hashMap 中删除。 重复直到 hashmap 为空。
如果依赖项列表通常很长,这将是低效的。 它适用于平均数量少于 5 个的直接依赖项。 如果由于执行了太多“重复直到 hashmap 为空”通道而导致性能问题,则应使用表示依赖关系图的双向数据结构,或者可能使用在此通道上只有一个依赖关系的 map 条目的列表,因此是下一次传球的有力候选者。
这是未经测试的草图:
class Obj { String id; }
class ObjWrapper {
String id;
Obj obj;
String[] depends; // may be null, may have null entries
public ObjWrapper(Obj obj, String[] depends) {
this.id = obj.id;
this.obj = obj;
if ( depends != null )
this.depends = Arrays.copyOf(depends, depends.length);
}
}
// order the objects by dependency.
ArrayList<Obj> orderObjs(Iterable<ObjWrapper> objs)
{
ArrayList<Obj> output = new ArrayList();
HashMap<String, ObjWrapper> objMap = new HashMap();
for ( ObjWrapper obj : objs )
objMap.put(obj.id, obj);
while ( !objMap.isEmpty() ) {
Iterator<ObjWrapper> iter = objMap.values().iterator();
while ( iter.hasNext() ) {
ObjWrapper objWrapper = iter.next();
if ( !hasDependencies(objWrapper, objMap) ) {
output.add(objWrapper.obj);
// must use iter to remove from hash, or bad things happen.
iter.remove();
}
}
}
return output;
}
boolean hasDependencies(ObjWrapper objWrapper,
HashMap<String, ObjWrapper> objMap)
{
if ( objWrapper.depends == null ) return false;
for ( String depend : objWrapper.depends ) {
if ( depend != null )
if ( objMap.containsKey(depend) )
return true;
else
depend = null; // to speed up future passes
}
return false;
}
我发现你的要求有点不清楚。 但是,据我所知,您应该能够通过提供适当的比较器来实现这一点。
编辑现在您已经添加了一个示例,我认为您甚至不需要排序。 假设元素 X、Y 和 Z 必须在某个元素 A 之后。您所要做的就是将 X、Y 和 Z 移到列表的末尾。 这可以在O(n)
时间内完成,而不是排序的O(n logn)
。
或者,您可以将 A 移到列表的开头。
如果您在元素之间有一个顺序(即您可以说这个小于这个),那么合并排序(以及任何排序算法)实际上会对集合进行排序。
尝试正式(数学)表达您需要的最终顺序。
两个元素的顺序无关紧要这一事实并不意味着您的比较器必须返回 0。如果它们相等,它必须返回 0。
您已经实现了比较器(并将其传递给标准合并排序),如下所示:
int compare(Object o1, Object o2) {
if (o1 instanceOf NotMatter) {
if (o2 instanceOf NotMatter) {
return 0;
}
return -1;
}
if (o2 instanceOf NotMatter) {
return 1;
}
// ok, now we have two important objects
if (o1.better(o2) {
return 1;
}
if (o2.better(o1) {
return -1;
}
return 0;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.