我習慣於使用字典來表示python中的圖表,但是我遇到了大圖和複雜計算的一些嚴重的性能問題,所以我認爲我應該交叉使用鄰接矩陣來繞過散列表的開銷。我的問題是,如果我有一個形式爲g的圖:{node:{vertex:weight。 。 。 }。 。 。 },將其轉換爲基於列表的鄰接矩陣的最有效方法是什麼?在Python中使用字符創建鄰接列表
2
A
回答
2
可能不是最有效的,但一個簡單的方法來你的格式轉換爲一個列表的基礎上的鄰接矩陣看起來是這樣的:
g = {1:{2:.5, 3:.2}, 2:{4:.7}, 4:{5:.6, 3:.3}}
hubs = g.items() # list of nodes and outgoing vertices
size=max(map(lambda hub: max(hub[0], max(hub[1].keys())), hubs))+1 # matrix dimension is highest known node index + 1
matrix=[[None]*size for row in range(size)] # set up a matrix of the appropriate size
for node, vertices in hubs: # loop through every node in dictionary
for vertice, weight in vertices.items(): # loop through vertices
matrix[vertice][node] = weight # define adjacency of both nodes by assigning the vertice's weight
這適用於向圖假定節點代表只需通過從零開始的索引。這裏是一個可視化和在此示例中處理的圖形生成的矩陣:
0 1 2 3 4 5
------------------------------
0 |
1 |
2 | 0.5
3 | 0.2 0.3
4 | 0.7
5 | 0.6
如果你的圖其實是在指導,我能想到的一些機會來優化的。如果字典containes每個節點與它的上市,就像{1:{2:.2, 3:.3}, 2:{1:.2}, 3:{1:.3}}
頂點的關鍵,你可以穿越之前排序相應的列表,並限制了內部循環:通過使用binary search
hubs = sorted(g.items())
for node, vertices in hubs:
for vertice, weight in reversed(sorted(vertices.items())):
if vertice >= node:
matrix[vertice][node] = weight
matrix[node][vertice] = weight
else: # do only care about vertices that haven't been saved before,
break # continue with next node when the current one won't introduce any more vertices
你或許可以有這樣的更加高效。由於產生的矩陣顯然是鏡像對稱的,所以你可以走得更遠,只存儲它的一半。要做到這一點最簡單的方法也許是翻轉它在垂直軸上:
# unlike the one before, this sample doesn't rely on the dictionary containing every vertice twice
matrix=[[None]*size for row in range(size)]
for node, vertices in hubs:
for vertice, weight in vertices.items():
matrix[vertice][size-node-1] = weight
由於矩陣的一半被切斷,不是每一個查找的節點之間的頂點(u,v)
會工作,所以它必須是確保列的索引大於要查找的單元格的行:
u,v = sorted((u,v))
weight = matrix[v][u]
祝你好運!
0
那麼要在鄰接列表中實現,您可以創建兩個類,一個用於存儲關於頂點的信息。
# Vertex, which will represent each vertex in the graph.Each Vertex uses a dictionary
# to keep track of the vertices to which it is connected, and the weight of each edge.
class Vertex:
# Initialze a object of this class
# we use double underscore
def __init__(self, key):
# we identify the vertex with its key
self.id = key
# this stores the info about the various connections any object
# (vertex) of this class has using a dictionary which is called connectedTo.
# initially its not connected to any other node so,
self.connectedTo={}
# Add the information about connection between vertexes into the dictionary connectedTo
def addNeighbor(self,neighbor,weight=0):
# neighbor is another vertex we update the connectedTo dictionary (Vertex:weight)
# with the information of this new Edge, the key is the vertex and
# the edge's weight is its value. This is the new element in the dictionary
self.connectedTo[neighbor] = weight
# Return a string containing a nicely printable representation of an object.
def __str__(self):
return str(self.id) + ' connectedTo: ' + str([x.id for x in self.connectedTo])
# Return the vertex's self is connected to in a List
def getConnections(self):
return self.connectedTo.keys()
# Return the id with which we identify the vertex, its name you could say
def getId(self):
return self.id
# Return the value (weight) of the edge (or arc) between self and nbr (two vertices)
def getWeight(self,nbr):
return self.connectedTo[nbr]
正如您從註釋中看到,每個頂點存儲有用於識別它, 一個「關鍵」,它有一本字典「connectedTo」,這是關鍵,重量對所有連接的從這個頂點。連接頂點的關鍵和邊緣的權重。
現在,我們可以存儲這樣的頂點的使用可以這樣來實現圖形類的集合,
# The Graph class contains a dictionary that maps vertex keys to vertex objects (vertlist) and a count of the number of vertices in the graph
class Graph:
def __init__(self):
self.vertList = {}
self.numVertices = 0
# Returns a vertex which was added to the graph with given key
def addVertex(self,key):
self.numVertices = self.numVertices + 1
# create a vertex object
newVertex = Vertex(key)
# set its key
self.vertList[key] = newVertex
return newVertex
# Return the vertex object corresponding to the key - n
def getVertex(self,n):
if n in self.vertList:
return self.vertList[n]
else:
return None
# Returns boolean - checks if graph contains a vertex with key n
def __contains__(self,n):
return n in self.vertList
# Add's an edge to the graph using addNeighbor method of Vertex
def addEdge(self,f,t,cost=0):
# check if the 2 vertices involved in this edge exists inside
# the graph if not they are added to the graph
# nv is the Vertex object which is part of the graph
# and has key of 'f' and 't' respectively, cost is the edge weight
if f not in self.vertList:
nv = self.addVertex(f)
if t not in self.vertList:
nv = self.addVertex(t)
# self.vertList[f] gets the vertex with f as key, we call this Vertex
# object's addNeighbor with both the weight and self.vertList[t] (the vertice with t as key)
self.vertList[f].addNeighbor(self.vertList[t], cost)
# Return the list of all key's corresponding to the vertex's in the graph
def getVertices(self):
return self.vertList.keys()
# Returns an iterator object, which contains all the Vertex's
def __iter__(self):
return iter(self.vertList.values())
在這裏,我們有持有「numVertices」頂點的數量,有圖類 字典'vertList',其中有關鍵字和頂點(我們剛製作的類)對象出現在 圖中。 我們可以創建一個圖,如果你想無向圖,然後加入這一行the_graph.addEdge(node2_key,node1_key,cost)
這樣的連接將不被存儲爲一個連接到B,而連接到B和B連接通過調用
# Now lets make the graph
the_graph=Graph()
print "enter the number of nodes in the graph"
no_nodes=int(raw_input())
# setup the nodes
for i in range(no_nodes):
print "enter the "+str(i+1)+" Node's key"
the_graph.addVertex(raw_input())
print "enter the number of edges in the graph"
no_edges=int(raw_input())
print "enter the maximum weight possible for any of edges in the graph"
max_weight=int(raw_input())
# setup the edges
for i in range(no_edges):
print "For the "+str(i+1)+" Edge, "
print "of the 2 nodes involved in this edge \nenter the first Node's key"
node1_key=raw_input()
print "\nenter the second Node's key"
node2_key=raw_input()
print "\nenter the cost (or weight) of this edge (or arc) - an integer"
cost=int(raw_input())
# add the edge with this info
the_graph.addEdge(node1_key,node2_key,cost)
設置它到一個。 還要注意上面兩個類實現的縮進,它可能是不正確的。
相關問題
- 1. 如何在C++中使用向量對創建鄰接列表?
- 2. 從python中的矩陣創建鄰接列表圖表
- 3. 創建鄰接表
- 4. 創建圖形使用鄰接表
- 5. 創建列表與字符在Python
- 6. 爲DFS創建鄰接列表
- 7. 創建一個鄰接表
- 8. 創建鄰接單鏈表
- 9. 想使用字符串在列表中創建一個列表
- 10. 如何閱讀txt文件,並創建鄰接表Python字典
- 11. Python - 使用列表創建字典
- 12. 使用igraph創建鄰接網絡矩陣(或列表)igraph
- 13. 從鄰接表中創建無向圖
- 14. 繼續使用Python創建可能的字符串列表
- 15. Python創建列表字典
- 16. 從Python中的鄰接列表構建菜單樹
- 17. 在Python中創建列表的列表
- 18. 如何在python中創建許多字符的列表?
- 19. 如何在python中創建x個字符的列表?
- 20. 如何在繪製圖形後創建鄰接列表?
- 21. 如何在Python中使用分隔符連接列表列表
- 22. 試圖使用鏈接列表和向量使鄰接列表
- 23. 使用鄰接列表和鄰接矩陣的圖的大小?
- 24. 使用標籤列表和更大的列表在Python中創建字典
- 25. 如何使用range()從字符串中創建數字列表?
- 26. 從鄰接列表類別創建html表
- 27. 從python列表中創建字典
- 28. Python從列表中創建字典
- 29. 從文件創建鄰接表
- 30. 在Python/R中創建節點邊緣三角形鄰接圖
如果您遇到與鄰接列表表示有關的性能問題,那麼您可能需要切換到專用圖庫,而不是使用不同的純Python表示。看到[這個問題](http://stackoverflow.com/q/606516/68063)及其答案的一些建議。 –