【图论】【数据结构】图的深度优先与广度优先遍历、最短路径
用栈实现图的深度优先遍历,队列实现广度优先遍历。
深度优先遍历
#!/usr/bin/python3
import random
import enum
import itertools
import mathCol = enum.Enum("Color", ("White", "Gray", "Black"))def DFS(G, s):visited = set()Q = []Q.append(s)visited.add(s)while Q:u = Q.pop()print(u)for i in G[u]:if i not in visited:Q.append(i)visited.add(i)def BFS(G, s):visited = set()Q = []Q.append(s)visited.add(s)while Q:u = Q.pop(0)print(u)for i in G[u]:if i not in visited:Q.append(i)visited.add(i)class Vertex:_cnt = 0# @staticmethoddef __init__(self, u, col, pi):self._cnt += 1self.u = uself.col = colself.pi = piself.d = math.infself.dt = 0self.ft = 0@propertydef Count(self):return self._cntdef __repr__(self):# return "Vertex(%s, col %s, perceding %s)" % (self.u, self.col, self.pi)return "%s" % self.u# A* keep with reference book
def ABFS(G, s):s.col = Col.Grays.d = 0s.pi = NoneQ = []Q.append(s)while Q:u = Q.pop(0)for x in G[u]:if x.col == Col.White:x.col = Col.Grayx.d = u.d + 1x.pi = uQ.append(x)u.col = Col.Blackdef AShortestPath(G, s, e, path=[]):if e == s:print(s)path.append(s)returnelif e.pi == None:print("No path from", s, "to", e)else:AShortestPath(G, s, e.pi, path)print(e)path.append(e)def FindPath(G, s, e, p):# [] just for enhancing list +p += [s]if s == e:return pfor n in G[s]:if n not in p:np = FindPath(G, n, e, p)if np:return npreturn Nonedef findAllPath(graph, start, end, path=[]):path = path + [start]if start == end:return [path]paths = [] # 存储所有路径for node in graph[start]:if node not in path:newpaths = findAllPath(graph, node, end, path)for newpath in newpaths:paths.append(newpath)return pathsdef isNotRepeat(all, a):for i in all:s = set(i)sa = set(a)if sa.issubset(s):return Falsereturn Truedef findMaxClique(graph):print("Start")clique_set = []# 遍历该团的顶点,for a in graph.keys():# 遍历顶点,对每个顶点查找其相邻顶点,构建初始团cli_can = [a, graph[a][random.randrange(0, len(graph[a]))]]if isNotRepeat(clique_set, cli_can):for i in cli_can:# 对其相邻neighbour顶点,若已经在团内的跳过,判断可否加入团,nb = graph[i]for j in nb:if j in cli_can:continueelse:is_memb = Truefor ii in cli_can:if j not in graph[ii]:is_memb = Falsebreakif is_memb:cli_can.append(j)clique_set.append(cli_can)n_max = 0mc = None# 比较各个团的大小。for c in clique_set:num = len(c)if num > n_max:n_max = nummc = creturn mcif __name__ == "__main__":G = []v0 = Vertex("s", Col.White, None)v01 = Vertex("r", Col.White, None)v02 = Vertex("w", Col.White, None)v0.next = v01v01.next = v02G.append(v0)v1 = Vertex("w", Col.White, None)v11 = Vertex("s", Col.White, None)v12 = Vertex("t", Col.White, None)v13 = Vertex("x", Col.White, None)v1.next = v11v11.next = v12v12.next = v13G.append(v1)print("Broad First Search")Ga = {# 0"r": ["s", "v"],# 1"s": ["r", "w"],# 2"t": ["w", "x", "u"],# 3"u": ["t", "x", "y"],# 4"v": ["r"],# 5"w": ["s", "t", "x"],# 6"x": ["w", "t", "u", "y"],# 7"y": ["x", "u"],}BFS(Ga, "s")DFS(Ga, "s")path = []print("FindPath", FindPath(Ga, "s", "y", []))graph = {"A": ["B", "C", "D"],"B": ["E"],"C": ["D", "F"],"D": ["B", "E", "G"],"E": [],"F": ["D", "G"],"G": ["E"],}ap = []findAllPath(graph, "A", "G", ap)alph = "rstuvwxy"lv = [Vertex(i, Col.White, Vertex(None, None, None)) for i in itertools.chain(alph)]m = dict(zip(alph, range(len(alph))))Gb = {}for (k, v) in Ga.items():key = lv[m[k]]Gb[key] = [lv[m[i]] for i in v]print(Gb)ABFS(Gb, lv[m["s"]])path = []AShortestPath(Ga, lv[m["s"]], lv[m["u"]], path)print(path)
递归方式实现DFS,
import enum
import mathCol = enum.Enum("Color", ("White", "Gray", "Black"))class Vertex:_cnt = 0# @staticmethoddef __init__(self, u, col, pi):self._cnt += 1self.u = uself.col = colself.pi = piself.d = math.infself.dt = 0self.ft = 0@propertydef Count(self):return self._cntdef __repr__(self):# return "Vertex(%s, col %s, perceding %s)" % (self.u, self.col, self.pi)return "%s" % self.uclass SolutionDFS:def __init__(self):self.time = 0def ADFS_VISIT(self, G, u):self.time += 1u.dt = self.timeu.col = Col.Grayfor v in G[u]:if v.col == Col.White:v.pi = uself.ADFS_VISIT(G, v)u.col = Col.Blackself.time += 1u.ft = self.timedef ADFS(self, G):for v in G.keys():v.col = Col.Whitev.pi = Noneself.time = 0for v in G.keys():if v.col == Col.White:self.ADFS_VISIT(G, v)