圖論演算法初步-圖的python實現
阿新 • • 發佈:2019-01-07
圖的基本性質
圖的分類:圖可以分為有向圖和無向圖,如圖為無向圖:
另外,還可以將圖分為有權圖和無權圖,權表示兩個節點之間的某種關係,比如交通運輸網路中兩個地點的權值可以代表交通費用,如圖為有向圖:
連通性:有時候,可能有兩個區域的交通路線是沒有相連的,這就會產生很多不連通的區域,如圖就是不完全連通的:
簡單圖
圖的表示方法
鄰接矩陣
如圖為一個無向圖,要用具體的數值表示節點之間的關係,可以使用鄰接矩陣,假設這個矩陣是A,就表示第i個節點和第j個節點是否相連,為1表示相連,0表示不相連。
除此之外,還可以使用鄰接矩陣表示有向圖:
鄰接表
用鄰接矩陣來表示,每一行表示一個節點與其他所有節點是否相連,但對於鄰接表來說,一行只代表和他相連的節點:
可見鄰接表在空間上是更省資源的。
鄰接表適合表示稀疏圖,鄰接矩陣適合表示稠密圖。
圖的python實現
鄰接矩陣
class DenseGraph:
def __init__(self,n,directed = False):
self.n = n # number of vertex
self.m = 0 #number of edge
self.directed = directed
self.matrix = [[0 for i in range(n)] for i in range(n)]
def __str__(self):
for line in self.matrix:
print(str(line))
return '' # must return string
def getNumberOfEdge(self):
return self.m
def getNumberOfVertex(self):
return self.n
def hasEdge(self,v,w):
if 0 <= v <= self.n and 0 <= w <= self.n:
return self.matrix[v][w]
else:
raise Exception("vertex not in the Graph")
def addEdge(self,v,w):
if 0 <= v <= self.n and 0 <= w <= self.n:
if self.hasEdge(v,w):
return
self.matrix[v][w]= 1
if self.directed is False:
self.matrix[w][v] = 1
self.m += 1
else:
raise Exception("vertex not in the Graph")
鄰接表
lass Vertex(object):
def __init__(self,key):
self.id = key
self.connectedTo = {} #the key is vertex,value is weight
def addNeighbor(self, nbr, weight=0):
self.connectedTo[nbr] = weight
def __str__(self):
return str(self.id) + ' connectedTo: ' + str([x.id for x in self.connectedTo])
def getConnections(self):
return self.connectedTo.keys()
def getConnectionsId(self):
idList = []
for k in self.connectedTo.keys():
idList.append(k.getId())
return sorted(idList)
def getConnectionsIdAndWeight(self):
idList = []
for k in self.connectedTo.keys():
idList.append(k.getId())
weightList = list(self.connectedTo.values())
return {idList[i]: weightList[i] for i in range(len(idList))}
def getWeight(self, nbr):
return self.connectedTo[nbr]
def getId(self):
return self.id
class SparseGraph(object):
def __init__(self,directed=False,weighted=False):
self.vertDict = {} #key is the id of vertex,value is vertex
self.numVertices = 0
self.directed=directed
self.weighted=weighted
def addVertex(self,key):
self.numVertices = self.numVertices + 1
newVertex = Vertex(key)
self.vertDict[key] = newVertex
return newVertex
def getVertex(self,n):
if n in self.vertDict:
return self.vertDict[n]
else:
return None
def __contains__(self,n):
return n in self.vertDict
def addEdge(self,f,t,weight=0):
if f not in self.vertDict:
self.addVertex(f)
if t not in self.vertDict:
self.addVertex(t)
self.vertDict[f].addNeighbor(self.vertDict[t], weight)
if self.directed is False:
self.vertDict[t].addNeighbor(self.vertDict[f], weight)
def getVertices(self):
return list(self.vertDict.keys())
def getVertNum(self):
return self.numVertices
def __iter__(self):
return iter(self.vertDict.values())
def getAllInfo(self):
verticesList=[int(x) for x in list(self.getVertices())]
verticesList.sort()
if self.weighted:
for i in range(len(verticesList)):
print('vertex %s : %s' % (i, self.getVertex(i).getConnectionsIdAndWeight()))
else:
for i in range(len(verticesList)):
print('vertex %s : %s' %(i,self.getVertex(i).getConnectionsId()))
打印出來看一下:
def buildGraphFromFile(aGraph,filePath):
graphList=[]
with open(filePath,'r',encoding='utf-8') as f:
for line in f:
graphList.append([int(x) for x in re.split(r'\s+',line.strip())])
for i in range(len(graphList)):
aGraph.addEdge(graphList[i][0],graphList[i][1])
# g1=DenseGraph(13) #必須填入正確的結點個數。。。我真的覺得鄰接矩陣不好用
# buildGraphFromFile(g1,'/Users/huanghuaixian/desktop/testG1.txt')
# print(g1)
g2=SparseGraph()
buildGraphFromFile(g2,'/Users/huanghuaixian/desktop/testG2.txt')
g2.getAllInfo()