繁体   English   中英

Java:排序元素

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM