【发布时间】:2013-05-06 00:45:23
【问题描述】:
我正在研究我的 scala 印章并实现了一个小图形 Api 来跟踪添加到图形中的顶点和边。我有基本的 GraphLike 特征,并且有一个无向图类 (UnDiGraph) 和一个扩展 GraphLike 特征的有向图类 (DiGraph)。这是一些清单
trait GraphLike[T] {
val vertices: Map[T, VertexLike[T]]
def addEdge( a:T, b:T ): GraphLike[T]
def addVertex( t:T ): GraphLike[T]
def addVertex( vert: VertexLike[T] ): GraphLike[T]
def adjacency( t:T ): Option[ List[T] ] =
{
if ( vertices contains t )
Some( vertices(t).adjList )
else
None
}
def vertNum: Integer = vertices size
def edgeNum: Integer =
{
def summer( sum: Integer, ms: Map[T, VertexLike[T] ] ): Integer =
{
if ( ms.isEmpty )
sum
else
summer( sum + ms.head._2.adjList.size, ms.tail )
}
summer( 0, vertices )
}
def getVertex( t: T ): VertexLike[T] =
{
vertices( t )
}
def edgeExists( a:T, b:T ): Boolean =
{
try
{
if( vertices( a ).adjList contains b )
true
else
false
}catch {
case ex: NoSuchElementException => false
}
}
}
这是 Directe Graph 的样子。
class DiGraph[T](val vertices: Map[ T, VertexLike[ T ] ] = Map.empty ) extends GraphLike[T] {
def makeVertex( t:T ): VertexLike[T] = new Vertex( t )
def addEdge( a:T, b:T ): GraphLike[T] =
{
//Make sure vertices exist
if( edgeExists(a, b) )
this
else {
try {
vertices(b)
vertices(a)
} catch {
case ex: NoSuchElementException => println("Vertices not Found"); this
}
addVertex( vertices( a ) + b )
}
}
def addVertex( t:T ): DiGraph[T] =
{
if( vertices contains t ) this
else
new DiGraph[T]( vertices + ( t -> makeVertex(t) ) )
}
def addVertex( vert: VertexLike[T] ): DiGraph[T] =
{
new DiGraph[T]( vertices + ( vert.apply -> vert ) )
}
}
顶点存储在从类型 T 到 VertexLike[T] 的 Map 中。 Vertex Like 基本上保存了特定 Vertex 的邻接列表。这是 VertexLike 的样子:
trait VertexLike[T]
{
def addEdgeTo( dest: T ): VertexLike[T]
def adjList: List[T]
def +( dest: T) = addEdgeTo(dest)
def apply: T
}
class Vertex[T](t: T, adj: List[T] = List() ) extends VertexLike[T]
{
def apply() = t
def adjList = adj
def addEdgeTo( dest: T ) =
if( adjList contains dest )
this
else
new Vertex[T]( t, dest :: adjList )
}
(是的...我意识到类中的 apply 方法是无用的,它只适用于对象。稍后才意识到)。
无论如何,我有一个示例图,其中有大约 80,000 个顶点。将顶点添加到图表中花费的时间太长了。我试图以功能性和不可变的方式做事。每当您向图形添加顶点或边时,您都会得到一个新图形(我试图确保图形类型的构造函数没有做太多事情)。这是我用来从数据创建图表的客户端代码。
def GraphInstantiater: GraphLike[Int] =
{
println( "Total number of Vertices: " + synMap.keys.size )
def vertexAdder( ls: Iterable[Int], graph:GraphLike[Int] ): GraphLike[Int] =
if( ls.isEmpty) graph else vertexAdder( ls.tail, graph.addVertex( ls.head ) )
val gr = vertexAdder( synMap.keys, new DiGraph[Int]( Map() ) )
println( "Vertices added. Total: %d".format( gr.vertices.size ) )
gr
}
我知道构建新图表需要循环,但考虑到我在构造函数中做的不多,这真的很棒吗?会反复创建顶点地图不断引起问题(它是图形类的参数之一)。任何关于这种方法的瓶颈是什么的想法都将不胜感激。另外,如果您需要任何其他信息,请告诉我。
【问题讨论】:
-
如果图表的所有元素永远不可变,并且您通过添加/更新/删除节点来创建新图表,那么您可以通过以下方式创建新图表 1) 仅创建符合以下条件的新节点受到更改 2) 的影响,否则所有内容都将引用原始图表。类似于写时复制语义的概念
-
他已经在这样做了(他正在使用通过引用共享它们共同元素的不可变映射)
-
这个应该发到codereview.stackexchange.com吗?
-
我不知道 codereview...我会在那里发帖...谢谢...
标签: scala