Scala中与图相关的列表的拓扑排序
我的图表结构如下:Scala中与图相关的列表的拓扑排序,scala,graph,topological-sort,Scala,Graph,Topological Sort,我的图表结构如下: class Graph { private var nodes: Set[Node] = Set.empty[Node] def addEdges(edges: (Node, Node)*) { for ((a, b) <- edges) { nodes ++= List(a, b) a addDst b } } override def toString = { val sb = new StringB
class Graph {
private var nodes: Set[Node] = Set.empty[Node]
def addEdges(edges: (Node, Node)*) {
for ((a, b) <- edges) {
nodes ++= List(a, b)
a addDst b
}
}
override def toString = {
val sb = new StringBuilder
for (node <- nodes if node.dst.toList.sortWith(ordered).nonEmpty)
sb ++= "%s -> %s\n" format (node.toString, node.dst.mkString(", "))
sb.toString
}
def ordered(a: Node, b: Node): Boolean = {
var dst = a.dst
while (dst.nonEmpty) {
if (dst contains b)
return true
dst = dst.flatMap(_.dst)
}
return false
}
}
trait Node {
def dst = _dst
private var _dst: Set[Node] = Set.empty[Node]
def addDst(that: Node) {
this._dst += that
}
}
class CharNode(val n: Char) extends Node {
override def toString = n.toString
}
我在列表上使用sortWith,使用的是图的有序方法
输出为:
Other(wb2,f)
Other(wa1,d)
Other(wb1,e)
这是错误的,因为图中f在e之后
那么为什么这是错误的呢?有序方法是错误的吗?还是我犯了其他错误
提前感谢。如果您快速“调试”您的图形。有序的方法:
def ordered(a: Node, b: Node): Boolean = {
println("[ordered] a = %s, b = %s".format(a, b))
var dst = a.dst
while (dst.nonEmpty) {
if (dst contains b)
return true
dst = dst.flatMap(_.dst)
}
return false
}
您会注意到,f
和e
没有直接比较:
[ordered] a = d, b = f
[ordered] a = f, b = d
[ordered] a = e, b = d
[ordered] a = d, b = e
考虑到MvG的评论,我认为这是因为假设订单是全部的,而你的不是。然而,我找不到一个明确的参考,无论是对于任何SeqLike
方法,它是sortWith
的来源,还是java.util.array.sort
,它似乎是内部使用的sortWith
。如果您快速“调试”您的图形。有序的方法:
def ordered(a: Node, b: Node): Boolean = {
println("[ordered] a = %s, b = %s".format(a, b))
var dst = a.dst
while (dst.nonEmpty) {
if (dst contains b)
return true
dst = dst.flatMap(_.dst)
}
return false
}
您会注意到,f
和e
没有直接比较:
[ordered] a = d, b = f
[ordered] a = f, b = d
[ordered] a = e, b = d
[ordered] a = d, b = e
考虑到MvG的评论,我认为这是因为假设订单是全部的,而你的不是。然而,我找不到一个明确的参考,无论是对于任何SeqLike
方法,它是sortWith
的来源,还是java.util.Arrays.sort
,我都找不到明确的参考,sortWith似乎在内部使用它。我提出了一个基于图的拓扑排序的排序方法:
object Main extends App {
val graph = new Graph
val d = new CharNode('d')
val e = new CharNode('e')
val f = new CharNode('f')
val g = new CharNode('g')
val i = new CharNode('i')
val l = new CharNode('l')
graph.addEdges(
d -> l,
e -> i,
i -> f,
f -> g
)
case class Other(s: String, node: Node)
val other = List(Other("wb2", f), Other("wa1", d), Other("wb1", e))
println(other.sortWith { case (o1, o2) => graph.ordered(o1.node, o2.node) }.mkString("\n"))
}
object Main extends App {
val graph = new Graph
val d = new CharNode('d')
val e = new CharNode('e')
val f = new CharNode('f')
val g = new CharNode('g')
val i = new CharNode('i')
val l = new CharNode('l')
graph.addEdges(
d -> l,
e -> i,
i -> f,
f -> g
)
case class Other(s: String, node: Node)
val other = List(Other("wb2", f), Other("wa1", d), Other("wb1", e))
println(other.sorted(graph.ordering[Other](_.node)).mkString("\n"))
}
class Graph {
private var nodes: Set[Node] = Set.empty[Node]
def addEdges(edges: (Node, Node)*) {
for ((a, b) <- edges) {
nodes ++= List(a, b)
a addDst b
}
}
def ordering[T](f: T => Node = (x: Node) => x) = {
import collection.mutable
val inDegrees = mutable.HashMap.empty ++ nodes.map(n => n -> n.src.size)
val sorted = new mutable.ListBuffer[Node]()
val zeroInDegree = mutable.Stack[Node]()
zeroInDegree pushAll inDegrees.filter(_._2 == 0).keys
while (zeroInDegree.nonEmpty) {
val next = zeroInDegree.pop
sorted += next
for (after <- next.dst) {
val count = inDegrees(after) - 1
if (count == 0) zeroInDegree push after
inDegrees(after) = count
}
}
assert(sorted.toSet == nodes)
new Ordering[T] {
val lookup = (sorted zipWithIndex).toMap
def compare(a: T, b: T) = lookup(f(a)) compare lookup(f(b))
}
}
}
trait Node {
var dst: Set[Node] = Set.empty[Node]
var src: Set[Node] = Set.empty[Node]
def addDst(that: Node) {
this.dst += that
that.src += this
}
}
class CharNode(val n: Char) extends Node {
override def toString = n.toString
}
objectmain扩展应用程序{
val图形=新图形
val d=新的CharNode('d')
val e=新的字符节点('e')
val f=新的字符节点('f')
val g=新的字符节点('g')
val i=新的字符节点('i')
val l=新的字符节点('l')
图1.3.附录(
d->l,
e->i,
i->f,
f->g
)
案例类其他(s:字符串,节点:节点)
val other=列表(其他(“wb2”,f)、其他(“wa1”,d)、其他(“wb1”,e))
println(other.sorted(graph.ordering[other](.node)).mkString(“\n”))
}
类图{
私有变量节点:Set[Node]=Set.empty[Node]
def加法(边:(节点,节点)*){
对于((a,b)节点=(x:Node)=>x)={
导入集合.mutable
val inDegrees=mutable.HashMap.empty++nodes.map(n=>n->n.src.size)
val sorted=new mutable.ListBuffer[Node]()
val zeroInDegree=mutable.Stack[Node]()
zeroInDegree pushAll inDegrees.filter(u._2==0).keys
while(zeroInDegree.nonEmpty){
val next=zeroInDegree.pop
排序+=下一个
对于(在之后),我提出了基于图的拓扑排序实现排序:
object Main extends App {
val graph = new Graph
val d = new CharNode('d')
val e = new CharNode('e')
val f = new CharNode('f')
val g = new CharNode('g')
val i = new CharNode('i')
val l = new CharNode('l')
graph.addEdges(
d -> l,
e -> i,
i -> f,
f -> g
)
case class Other(s: String, node: Node)
val other = List(Other("wb2", f), Other("wa1", d), Other("wb1", e))
println(other.sortWith { case (o1, o2) => graph.ordered(o1.node, o2.node) }.mkString("\n"))
}
object Main extends App {
val graph = new Graph
val d = new CharNode('d')
val e = new CharNode('e')
val f = new CharNode('f')
val g = new CharNode('g')
val i = new CharNode('i')
val l = new CharNode('l')
graph.addEdges(
d -> l,
e -> i,
i -> f,
f -> g
)
case class Other(s: String, node: Node)
val other = List(Other("wb2", f), Other("wa1", d), Other("wb1", e))
println(other.sorted(graph.ordering[Other](_.node)).mkString("\n"))
}
class Graph {
private var nodes: Set[Node] = Set.empty[Node]
def addEdges(edges: (Node, Node)*) {
for ((a, b) <- edges) {
nodes ++= List(a, b)
a addDst b
}
}
def ordering[T](f: T => Node = (x: Node) => x) = {
import collection.mutable
val inDegrees = mutable.HashMap.empty ++ nodes.map(n => n -> n.src.size)
val sorted = new mutable.ListBuffer[Node]()
val zeroInDegree = mutable.Stack[Node]()
zeroInDegree pushAll inDegrees.filter(_._2 == 0).keys
while (zeroInDegree.nonEmpty) {
val next = zeroInDegree.pop
sorted += next
for (after <- next.dst) {
val count = inDegrees(after) - 1
if (count == 0) zeroInDegree push after
inDegrees(after) = count
}
}
assert(sorted.toSet == nodes)
new Ordering[T] {
val lookup = (sorted zipWithIndex).toMap
def compare(a: T, b: T) = lookup(f(a)) compare lookup(f(b))
}
}
}
trait Node {
var dst: Set[Node] = Set.empty[Node]
var src: Set[Node] = Set.empty[Node]
def addDst(that: Node) {
this.dst += that
that.src += this
}
}
class CharNode(val n: Char) extends Node {
override def toString = n.toString
}
objectmain扩展应用程序{
val图形=新图形
val d=新的CharNode('d')
val e=新的字符节点('e')
val f=新的字符节点('f')
val g=新的字符节点('g')
val i=新的字符节点('i')
val l=新的字符节点('l')
图1.3.附录(
d->l,
e->i,
i->f,
f->g
)
案例类其他(s:字符串,节点:节点)
val other=列表(其他(“wb2”,f)、其他(“wa1”,d)、其他(“wb1”,e))
println(other.sorted(graph.ordering[other](.node)).mkString(“\n”))
}
类图{
私有变量节点:Set[Node]=Set.empty[Node]
def加法(边:(节点,节点)*){
对于((a,b)节点=(x:Node)=>x)={
导入集合.mutable
val inDegrees=mutable.HashMap.empty++nodes.map(n=>n->n.src.size)
val sorted=new mutable.ListBuffer[Node]()
val zeroInDegree=mutable.Stack[Node]()
zeroInDegree pushAll inDegrees.filter(u._2==0).keys
while(zeroInDegree.nonEmpty){
val next=zeroInDegree.pop
排序+=下一个
例如(我不知道scala,但大多数列表排序算法只适用于总顺序。如果一个图有不可比较的节点,即使它们不相等,也会使它们混淆。我不久前为有向无环图写了一篇文章。compare
方法是O(N),所以可能会有更好的算法。但是它对顶点施加了一个总的顺序,所以这里应该会给出正确的结果。我不知道scala,但是大多数列表排序算法只对总的顺序有效。如果一个图有不可比的节点,即使它们不相等,也会混淆它们。我曾经为有向无环图写过一篇文章e.比较的方法是O(N),因此可能会有更好的算法。但它对顶点施加了总顺序,因此这里应该会给出正确的结果。通过PartialOrdering
或PartiallyOrdered
支持偏序,这两种方法都不被排序方法使用。是的,这就是我刚刚发现的。我现在正在尝试实现一种排序方法它支持PartialOrdering。通过PartialOrdering
或PartialYordered
支持部分排序,排序方法都不使用这两种方法。是的,这就是我刚刚发现的。我现在正尝试实现一种支持PartialOrdering的排序方法。