仅当特定对象具有可比性时排序设置

时间:2017-06-06 09:48:04

标签: java sorting data-structures

我有一组独特的数据。让我们说它看起来像这样:

0: domainA.org -> domainB.org
1: domainY.org -> domainZ.org
2: domainB.org -> domainC.org
3: domainD.org -> domainE.org
4: domainX.org -> domainY.org
5: domainC.org -> domainD.org

为了将与domainA.org相关的数据复制到B C D和E以及doimanY.org到X和Z,我需要按以下顺序迭代这个集:

0: domainA.org -> domainB.org
2: domainB.org -> domainC.org
5: domainC.org -> domainD.org
3: domainD.org -> domainE.org

4: domainX.org -> domainY.org
1: domainY.org -> domainZ.org

X -> Y -> ZA -> B -> C -> D -> E之前处理它们并不重要。

对每个"类别进行排序"例如每个独立的数据部分都很容易。 我为sourceDomain -> destinationDomain实现了Comparable的包装对象,并使用了SortedSet为我做了排序。 现在问题出现了。
这就是我的comparteTo实现的样子:

if (source.equals(other.destination)) {
    return 1;
} else if (destination.equals(other.source)) {
    return -1;
}
return 0;

它只能比较2个对象,如果它们在最终列表中彼此相邻,那么它就是"对待"其他对象是一样的。
(更不用说如果compareTo在某个时刻返回0,则TreeSet不会向其自身添加项目) 因此,它没有正确排序我在示例1中显示的数据 我的想法是迭代源集并添加对每个其他条目的条目进行比较,并创建单独的集合,我可以在完成排序后将它们连接在一起。
这种复杂性至少是n ^ 2,这是非常糟糕的 我的问题:我们能做得更好吗?

1 个答案:

答案 0 :(得分:2)

您正在寻找的是图表中的拓扑排序。有许多算法可以解决这个问题,可以在the Wikipedia article上的伪代码中找到。

最容易实现的是深度优先搜索,有点复制如下:

L ← Empty list that will contain the sorted nodes
foreach node n do
    if not marked n then visit(n) 

function visit(node n)
    if n has a temporary mark then stop (cyclic dependency found!)
    if n is not marked (i.e. has not been visited yet) then
        mark n temporarily
    for each node m with an edge from n to m do
        visit(m)
        mark n permanently
        unmark n temporarily
        add n to head of L

这最多具有时间复杂度O(节点+边缘),在您的情况下,似乎节点=边缘,因此足够快。