我正在研究我的scala排版,並實現了一個小圖形Api來跟蹤添加到圖形中的頂點和邊。我有基本的GraphLike Trait,並具有擴展GraphLike
特性的無向圖類(UnDiGraph
)和有向圖類(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]。頂點像基本上持有特定頂點的鄰接列表。繼承人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)
}
(是的......我知道在類的應用方法是無用的,它只能在對象意識到稍後)。
無論如何,我有一個示例圖,我有大約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)否則一切都是對原始圖形的引用。類似的概念寫作時複製語義 – Patashu 2013-05-03 04:11:55
他已經在做這個(他使用不變的地圖,通過引用分享他們的共同元素) – 2013-05-03 06:12:50
這應該發佈在http://codereview.stackexchange.com/? – Dahdahm 2013-05-03 13:16:09