Java:对元素进行排序
我知道我们通常使用。JavaDoc说它是一个修改过的mergesort 但我需要一个排序算法,可以比较每个对象和每个对象。我会有很多元素,顺序并不重要。但有些元素确实需要在特定的其他元素之后出现(不一定是连续的)。我认为(但不知道)合并排序是不够的 也许,我想要实现的甚至不是所谓的排序 我是否需要自己实施这样一个系统,或者是否存在这样一个系统Java:对元素进行排序,java,sorting,Java,Sorting,我知道我们通常使用。JavaDoc说它是一个修改过的mergesort 但我需要一个排序算法,可以比较每个对象和每个对象。我会有很多元素,顺序并不重要。但有些元素确实需要在特定的其他元素之后出现(不一定是连续的)。我认为(但不知道)合并排序是不够的 也许,我想要实现的甚至不是所谓的排序 我是否需要自己实施这样一个系统,或者是否存在这样一个系统 例如: Obj1, Obj2, Obj3, Obj4 以下几对的顺序无关紧要(这意味着我的比较器应该返回0): 但是!Obj4后面跟着Obj1是非常必
例如:
Obj1, Obj2, Obj3, Obj4
以下几对的顺序无关紧要(这意味着我的比较器应该返回0):
但是!Obj4后面跟着Obj1是非常必要的
由于有两个(*)对,这在数学上意味着Obj1==Obj4
使用mergesort可以工作吗
谢谢如果您知道理想的排序,一个选项是添加一些可排序的值,如表示数据之间关系的整数。例如,如果项目A必须位于项目B之前,则确保其排序值小于项目B的值。然后,您可以提供一个只查看排序值的自定义比较器,并且可以使用标准排序算法。我发现您的要求有点不清楚。然而,从我收集的信息来看,您应该能够通过提供适当的比较器来实现这一点 编辑现在您已经添加了一个示例,我认为您甚至不需要排序。假设元素X、Y和Z必须在某个元素A之后。您所要做的就是将X、Y和Z移到列表的末尾。这可以在
O(n)
时间内完成,而不是排序的O(n logn)
或者,您可以将A移到列表的开头。如果元素之间有顺序(即,您可以说这个比这个小),那么合并排序(以及任何排序算法)实际上会对集合进行排序 试着用形式(数学)表达你需要的最终顺序
两个元素的顺序无关紧要这一事实并不意味着比较器必须返回0。如果它们相等,它必须返回0 iif。您已经实现了comparator(并将其传递给标准mergesort),类似于:
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;
}
听起来你有一组DAG(有向无环图)。我认为你需要对此建模,然后对每一个进行拓扑排序。一种方法: 将每个元素包装在一个包装器对象中,该包装器对象引用该对象,并具有一个用于保存对其他对象的依赖关系的列表。将所有这些包装器放在由对象id键控的哈希映射中 对于没有直接依赖关系的所有元素,发出该元素,并将其从hashMap中删除。重复此操作,直到hashmap为空 如果依赖项列表通常很长,这将是低效的。它适用于平均数量小于5的直接依赖项。如果性能是一个问题,因为执行了太多的“重复直到hashmap为空”过程,那么应该使用一个双向数据结构来表示依赖关系图,或者可能使用一个映射项列表,这些映射项在此过程上只有一个依赖关系,因此是下一个过程的强候选项 这是一个未经测试的草图:
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;
}
class Obj{String id;}
类ObjWrapper{
字符串id;
Obj-Obj;
字符串[]依赖;//可能为空,可能有空条目
公共ObjWrapper(Obj Obj,字符串[]取决于){
this.id=obj.id;
this.obj=obj;
如果(取决于!=null)
this.dependens=Arrays.copyOf(dependens,dependens.length);
}
}
//按依赖项对对象进行排序。
ArrayList orderObjs(Iterable objs)
{
ArrayList输出=新的ArrayList();
HashMap objMap=新的HashMap();
for(ObjWrapper-obj:objs)
objMap.put(obj.id,obj);
而(!objMap.isEmpty()){
迭代器iter=objMap.values().Iterator();
while(iter.hasNext()){
ObjWrapper ObjWrapper=iter.next();
if(!hasDependencies(objWrapper,objMap)){
add(objWrapper.obj);
//必须使用iter从散列中删除,否则会发生不好的事情。
iter.remove();
}
}
}
返回输出;
}
布尔hasDependencies(ObjWrapper ObjWrapper,
HashMap(objMap)
{
if(objWrapper.depends==null)返回false;
for(字符串依赖:objWrapper.depends){
如果(依赖!=null)
if(对象映射容器(依赖))
返回true;
其他的
depend=null;//以加快将来的传递
}
返回false;
}
使用比较器可以而且应该很好地实现您的自定义排序。请您通过发布一个简单(但完整)的示例来澄清您的要求?您应该进一步澄清您希望如何“排序”您的元素。您能在这里详细介绍一下用例吗?我怀疑您正在寻找“拓扑排序”,但根据您的描述很难判断。我认为您上面的推测可能是正确的:您想要的不是排序。我这样说是因为您上面定义的标识规则:(如果Obj2必须遵循Obj1,Obj4必须遵循Obj2,那么Obj1==Obj4)。无论“必须遵循”什么意思是,这与排序无关。如果排序值可以从已经存在的值快速计算,则可能不需要额外的字段。是的,这是真的!这取决于对象的工作方式以及计算该值是否花费了很长时间,等等。但这一点很好。
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;
}