图形结构,是树形结构的扩展。
我们在回溯法里面了解到几种结构:二叉树,排列树,完全n叉树,这几种解空间类型,都可以直接使用回溯法的框架解决。
二叉树,排列树,完全n叉树,都可以看成x叉树的变形,而图形结构就是x叉树。
在此之前,我们先明白一点:一颗二叉树是什么,他是某一颗二叉树的子树,同样的道理,一个图是什么,他是某个图的子图。
一般的二叉树问题,我们先处理当前结点,再处理左子树和右子树,对应一般的图的问题,我们先处理当前顶点,再依次处理各个子图。
在回溯法里,都是看成解空间的深入,对应这里的就是子问题的逐步变小,回溯法使用条件是:解空间满足多米诺性质,也就是部分解不满足最终解,部分解后面的解也就不满足最终解,子问题的逐步缩小也是满足多米诺性质的。
图的宽度优先遍历,和限界分支法类似,应该可以使用基于队列方式或者优先级队列的方式,因为图是一般形式的x叉树,每一层的叉不知道几个,都是借助于标记来判断是否完全遍历的,注意标记visited的用法。
又思考了一下,为什么图会使用标记visited,其本质是:一个图分解成:当前顶点+相邻顶点各个子图,这种划分是分治,但是划分的子问题有重叠,子问题多且相互不独立时,使用动态规划编程时使用备忘模型,一般使用标记数组避免重复计算子问题。
g = {'A':{'B':1,'C':2},
'B':{'A':1,'C':3,'D':4},
'C':{'A':2,'B':3,'D':5,'E':6},
'D':{'B':4,'C':5,'E':7,'F':8},
'E':{'C':6,'D':7,'G':9},
'F':{'D':8},
'G':{'E':9}
}
def BFS(graph,start_vertex):
queue =[start_vertex,]
visited = set()
result = []
while queue:
current_vertex = queue.pop(0)
if current_vertex not in visited:
result.append(current_vertex)
visited.add(current_vertex)
for neighbour_vertex in graph[current_vertex].keys():
queue.append(neighbour_vertex)
return result
def BFS2(graph,start_vertex):
queue = [start_vertex,]
visited = set()
visited.add(start_vertex)
result =[]
while queue:
current_vertex = queue.pop(0)
result.append(current_vertex)
for neighbour_vertex in graph[current_vertex].keys():
if neighbour_vertex not in visited:
queue.append(neighbour_vertex)
visited.add(neighbour_vertex)
return result
图的深度优先遍历:
def DFS(graph,start_vertex):
def DFSRecursion(graph,start_vertex,visited):
result.append(start_vertex)
for neighbour_vertex in graph[start_vertex].keys():
if neighbour_vertex not in visited:
visited.add(neighbour_vertex)
DFSRecursion(graph,neighbour_vertex,visited)
result =[]
visited = set()
visited.add(start_vertex)
DFSRecursion(graph,start_vertex,visited)
return result
def DFS2(graph,start_vertex):
visited = set()
visited.add(start_vertex)
stack =[start_vertex,]
result = []
while stack:
current_vertex = stack.pop()
result.append(current_vertex)
for neighbour_vertex in graph[current_vertex].keys():
if neighbour_vertex not in visited:
visited.add(neighbour_vertex)
stack.append(neighbour_vertex)
return result
测试结果:
print(BFS(g,'A'))
print(BFS2(g,'A'))
print(DFS(g,'A'))
print(DFS2(g,'A'))
runfile('D:/share/test/graph.py', wdir='D:/share/test')
['A', 'B', 'C', 'D', 'E', 'F', 'G']
['A', 'B', 'C', 'D', 'E', 'F', 'G']
['A', 'B', 'C', 'D', 'E', 'G', 'F']
['A', 'C', 'E', 'G', 'D', 'F', 'B']
不要认为深度优先遍历的递归方式和迭代方式结果不一样,假如需要一样,那迭代栈实现方式就需要逆序放入栈。