Graph 和 Vertex 构建基于邻接列表:
# -*- coding: utf-8 -*-
# @Date : 2019/12/1
# @File : AdjListGraph.py
import sys
class Vertex(object):
def __init__(self, node):
self.id = node
self.adjacent = {} # 存该节点的邻居及其边权重
self.distance = sys.maxsize
self.visited = False
self.previous = None
def addNeighbor(self, neighbor, weight=0):
self.adjacent[neighbor] = weight
def getConnections(self):
return self.adjacent.keys()
def getVertexID(self):
return self.id
def setVertexID(self, id):
self.id = id
def getWeight(self, neighbor):
return self.adjacent.get(neighbor)
def setDistance(self, dist):
self.distance = dist
def getDistance(self):
return self.distance
def setPrevious(self, prev):
self.previous = prev
def setVisited(self):
self.visited = True
# 打印节点时显示的信息
def __str__(self):
return str(self.id) + " adjacent: " + str([x.id for x in self.adjacent])
def __lt__(self, other):
return self.distance < other.distance and self.id < other.id
class Graph(object):
def __init__(self, directed=False):
self.vertexDict = {} # key:id value:Vertex(id)
self.numVertices = 0
self.directed = directed
def __iter__(self):
return iter(self.vertexDict.values())
def isDirected(self):
return self.directed
def vertexCount(self):
return self.numVertices
def addVertex(self, node):
self.numVertices = self.numVertices + 1
newVertex = Vertex(node)
self.vertexDict[node] = newVertex
return newVertex
def getVertex(self, n):
return self.vertexDict.get(n)
def addEdge(self, frm, to, cost=0):
if frm not in self.vertexDict:
self.addVertex(frm)
if to not in self.vertexDict:
self.addVertex(to)
self.vertexDict[frm].addNeighbor(self.vertexDict[to], cost)
if not self.directed:
self.vertexDict[to].addNeighbor(self.vertexDict[frm], cost)
def getVertices(self):
# return ids
return self.vertexDict.keys()
# def setPrevious(self, current):
# self.previous = current
#
# def getPrevious(self, current):
# return self.previous
def getEdges(self):
edges = []
for key, currentVertex in self.vertexDict.items():
for neighbor in currentVertex.getConnections():
currentVertexID = currentVertex.getVertexID()
neighborID = neighbor.getVertexID()
edges.append((currentVertexID, neighborID, currentVertex.getWeight(neighbor)))
return edges
def getNeighbors(self, v):
vertex = self.vertexDict[v]
return vertex.getConnections()
if __name__ == '__main__':
G = Graph(True)
G.addVertex('a')
G.addVertex('b')
G.addVertex('c')
G.addVertex('d')
G.addVertex('e')
G.addVertex('f')
G.addEdge('a', 'b', 1)
G.addEdge('a', 'c', 1)
G.addEdge('b', 'd', 1)
G.addEdge('b', 'e', 1)
G.addEdge('c', 'd', 1)
G.addEdge('c', 'e', 1)
G.addEdge('d', 'e', 1)
G.addEdge('e', 'a', 1)
print(G.getEdges())
for k in G.getEdges():
print(k)
print()
for key in G.vertexDict:
# 对应 Vertex中的__str__
print(key, 'corresponds to', G.vertexDict[key])
print()
v = 'a'
neighbors = G.getNeighbors(v)
for n in neighbors:
print(n)
# 基于边的结合构建图
def graphFromEdgeList(E, directed=False):
"""Make a graph instance based on a sequence of edge tuples.
Edges can be either of from (origin,destination) or
(origin,destination,element). Vertex set is presume to be those
incident to at least one edge.
vertex labels are assumed to be hashable.
"""
g = Graph(directed)
# 得到所有节点名称
V = set()
for e in E:
V.add(e[0])
V.add(e[1])
print("Vertex :", V)
# 构建图节点vertex
vertices = {}
for v in V:
vertices[v] = g.addVertex(v)
print(g.vertexCount())
# 根据边集合为节点添加边
for e in E:
src = e[0]
dest = e[1]
cost = e[2] if len(e) > 2 else None
g.addEdge(src, dest, cost)
return g
E2 = (
('A', 'B', 1), ('A', 'C', 1),
)
graph = graphFromEdgeList(E2, True)
for k in graph.getEdges():
print(k)
print()
E = (
('SFO', 'LAX', 337), ('SFO', 'BOS', 2704), ('SFO', 'ORD', 1846),
('SFO', 'DFW', 1464), ('LAX', 'DFW', 1235), ('LAX', 'MIA', 2342),
('DFW', 'ORD', 802), ('DFW', 'MIA', 1121), ('ORD', 'BOS', 867),
('ORD', 'JFK', 740), ('MIA', 'JFK', 1090), ('MIA', 'BOS', 1258),
('JFK', 'BOS', 187),
)
graph = graphFromEdgeList(E, True)
for e in graph.getEdges():
print(e)
for m in graph.getVertices():
print(m)
DFS:
# -*- coding: utf-8 -*-
# @Date : 2019/12/1
# @File : DepthFirstSearch.py
from AdjListGraph import Graph, Vertex
def __dfsHelper(s, G, visited, parents):
# if s == G:
# return
if s not in visited:
visited[s.getVertexID()] = True
print("traversal: ", s.getVertexID())
for neighbor in s.getConnections():
if neighbor.getVertexID() not in visited:
parents[neighbor.getVertexID()] = s.getVertexID()
__dfsHelper(neighbor, G, visited, parents)
# print(parents)
def DFSRecursive(G):
visited = {}
parents = {}
for node in G:
if node.getVertexID() not in visited:
__dfsHelper(node, G, visited, parents)
print(visited)
print(parents)
def DFSIterative(G, start, dest):
stack = []
parents = {}
visited = set()
stack.append(start)
while stack:
node = stack.pop()
print("traversal: ", node.getVertexID())
if node.getVertexID() == dest.getVertexID():
return parents
# if node not in visited:
visited.add(node.getVertexID())
for neighbor in G.getNeighbors(node.getVertexID()):
if neighbor not in visited:
stack.append(neighbor)
parents[neighbor.getVertexID()] = node.getVertexID()
return None
if __name__ == '__main__':
G = Graph(directed=True)
G.addVertex('a')
G.addVertex('b')
G.addVertex('c')
G.addVertex('d')
G.addVertex('e')
G.addVertex('f')
G.addEdge('a', 'b', 1)
G.addEdge('a', 'c', 1)
G.addEdge('b', 'd', 1)
G.addEdge('b', 'e', 1)
G.addEdge('c', 'd', 1)
G.addEdge('c', 'e', 1)
G.addEdge('d', 'e', 1)
G.addEdge('e', 'a', 1)
G.addEdge('a', 'f', 1)
print(G.getEdges())
for k in G.getEdges():
print(k)
visited = {}
parents = {}
DFSRecursive(G)
print()
# 从v节点开始遍历
v = G.getVertex('e')
__dfsHelper(v, G, visited, parents)
#
print("#"*20)
start = G.getVertex('a')
dest = G.getVertex('e')
print(DFSIterative(G, start=start, dest=dest))
BFS:
# -*- coding: utf-8 -*-
# @Date : 2019/12/1
# @File : BreadthFirstSearch.py
from AdjListGraph import Graph
from collections import deque
def BFSIterative(G, start, dest):
queue = deque()
visited = set()
parents = {}
queue.append(start)
while queue:
node = queue.popleft()
print("visiting :", node.getVertexID())
if node.getVertexID() == dest.getVertexID():
return parents
visited.add(node.getVertexID())
for neighbor in G.getNeighbors(node.getVertexID()):
if neighbor not in visited:
queue.append(neighbor)
parents[neighbor.getVertexID()] = node.getVertexID()
return None
if __name__ == '__main__':
G = Graph(directed=True)
G.addVertex('a')
G.addVertex('b')
G.addVertex('c')
G.addVertex('d')
G.addVertex('e')
G.addVertex('f')
G.addEdge('a', 'b', 1)
G.addEdge('a', 'c', 1)
G.addEdge('a', 'f', 1)
G.addEdge('b', 'd', 1)
G.addEdge('b', 'e', 1)
G.addEdge('c', 'd', 1)
G.addEdge('c', 'e', 1)
G.addEdge('d', 'e', 1)
G.addEdge('e', 'a', 1)
print(G.getEdges())
for k in G.getEdges():
print(k)
#
print("#" * 20)
start = G.getVertex('a')
dest = G.getVertex('e')
print(BFSIterative(G, start=start, dest=dest))
DFS vs BFS: