深度优先搜索(DFS)是一种有效的图遍历方法,类似于二叉树的前序/中序/后续遍历,其从初始搜索节点开始,递归的向下搜索。
# 1. 创建Vertex对象
class Vertex(object):
"""
节点对象,在基础节点对象的基础上,添加了关于着色、前驱节点以及距离的相关属性和方法
"""
def __init__(self, key):
self.key = key
self.connectedTo = {} # 存放指向的其它节点,以Vertex:连接边weight的
self.color = "white" # BFS中的状态标记
self.predecessor = None # BFS时前驱节点的标记
self.time = [0, 0] # [search_time, finish_time], 分别表示开始探索该节点子图,以及结束探索该节点所在子图的时间
def addNeighbor(self, nbr, weight):
self.connectedTo.update({nbr: weight})
def __str__(self):
return str(self.key) + '-->' + str([nbr.key for nbr in self.connectedTo])
def getConnections(self):
return self.connectedTo.keys()
def getId(self):
return self.key
def getWeight(self, nbr):
weight = self.connectedTo.get(nbr)
if weight is not None:
return weight
else:
raise KeyError("No such nbr exist!")
def getColor(self):
return self.color
def setColor(self, color):
self.color = color
def setPredecessor(self, vertex):
self.predecessor = vertex
def getPredecessor(self):
return self.predecessor
def setSearchTime(self, time):
self.time[0] = time
def setFinishTime(self, time):
self.time[1] = time
# 2. 创建Graph对象
class Graph(object):
"""
图对象
"""
def __init__(self):
self.vertexList = {} # 字典保存节点信息,以{key: Vertex}的方式
self.vertexNum = 0 # 统计图节点数
self.time = 0 # DFS遍历所有节点所需的步骤
def addVertex(self, key):
self.vertexList.update({key: Vertex(key)})
self.vertexNum += 1
def getVertex(self, key):
vertex = self.vertexList.get(key)
return vertex
def __contains__(self, key):
return key in self.vertexList.values()
def addEdge(self, f, t, weight=0):
if not self.getVertex(f):
self.addVertex(f)
if not self.getVertex(t):
self.addVertex(t)
self.vertexList[f].addNeighbor(self.vertexList[t], weight=weight)
def getVertices(self):
return self.vertexList.keys()
def __iter__(self):
return iter(self.vertexList.values())
def dfs(self):
for startVertex in self: # type: Vertex
if startVertex.getColor() == 'white':
self._dfs(startVertex) # 以所有节点为子图起始点进行遍历,防止有非联通子图
def _dfs(self, startVertex: Vertex):
startVertex.setColor('gray')
self.time += 1
startVertex.setSearchTime(self.time)
for aVertex in startVertex.getConnections(): # type: Vertex
if aVertex.getColor() == 'white':
aVertex.setPredecessor(startVertex)
self._dfs(aVertex)
startVertex.setColor('black')
self.time += 1
startVertex.setFinishTime(self.time)
if __name__ == '__main__':
g = Graph()
g.addEdge('A', 'B')
g.addEdge('B', 'C')
g.addEdge('A', 'D')
g.addEdge('B', 'D')
g.addEdge('D', 'E')
g.addEdge('E', 'F')
g.addEdge('E', 'B')
g.addEdge('F', 'C')
g.dfs()
print(g.time)
print(g.getVertex('B').time)