我有一组独特的数据。让我们说它看起来像这样:
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 -> Z
在A -> 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,这是非常糟糕的
我的问题:我们能做得更好吗?
答案 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(节点+边缘),在您的情况下,似乎节点=边缘,因此足够快。