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)
这是错误的,因为图中fe之后

那么为什么这是错误的呢?有序方法是错误的吗?还是我犯了其他错误

提前感谢。

如果您快速“调试”您的
图形。有序的
方法:

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的排序方法。