关于书中深度优先遍历的非递归算法 (p237),和我自己写的递归式的深度优先遍历(占个坑先)
1. 问题
书中的算法并不完全,只能处理我们给出顶点v0
的出边;当v0
的出边处理完成后,就会退出循环,没有处理图中的其它顶点。
以下是我写的测试函数:
def testGraphAL():
graph1 = GraphAL([[0, 1, 1, 0],
[1, 0, 1, 0],
[1, 1, 0, 1],
[0, 0, 1, 0]])
graph1.add_vertex()
print("\n" + "*" * 12 + "\n")
print("\n顶点为 :0、1、2、3、4\n")
print("关系 :%s" % graph1._mat)
print("\n\t从v0 = 1 开始:\n")
print("\nmy_DFS : \n")
print(my_DFS(graph1, 1, [])) # 这里的`[]`是个问题,
# 如果没有显示的给出,
# 就会将上一次调用函数后产生的`d_list`传进下一次调用
print("\nbook_DFS : \n")
print(book_DFS(graph1, 1))
graph2 = GraphAL([[0, 0, 1],
[1, 0, 1],
[0, 1, 0]])
print("\n" + "*" * 12 + "\n")
print("\n顶点为 :0、1、2\n")
print("关系 :%s" % graph2._mat)
print("\n\t从v0 = 0 开始:\n")
print("\nmy_DFS : \n")
print(my_DFS(graph2, 0, []))
print("\nbook_DFS : \n")
print(book_DFS(graph2, 0))
graph3 = GraphAL([[0, 0, 0],
[0, 0, 0],
[0, 0, 0]])
print("\n" + "*" * 12 + "\n")
print("\n顶点为 :0、1、2\n")
print("关系 :%s" % graph3._mat)
print("\n\t从v0 = 0 开始:\n")
print("\nmy_DFS : \n")
print(my_DFS(graph3, 0, []))
print("\nbook_DFS : \n")
print(book_DFS(graph3, 0))
说明:这里我创建了三种不同的关系
graph1:调用了add_vertex()方法,添加了一个新顶点,这个顶点与其他顶点间没有边(基于p226页的图G6,并加入一个新顶点)
graph2:是一个强连通有向图(p226页的图G5)
graph3:图中任何顶点之间均没有边
如果使用这个测试函数,请改成自己深度遍历算法的函数名。
当对书中的实现调用这个测试时候,你会发现当存在独立的顶点时,函数并没有遍历它们;这是由于在循环中,只处理了初始顶点的出边,不被出边包含的顶点并没有被push
进栈。
这个函数适用于有根图,并且我们给的起始顶点恰好是一个根。
修改函数:
def book_DFS(graph, v0):
vnum = graph.vertex_num()
visited = [0] * vnum
visited[v0] = 1
DFS_sqe = [v0]
st = SStack()
st.push((0, graph.out_edges(v0)))
while not st.is_empty():
i, edges = st.pop()
if i < len(edges):
v, val = edges[i]
st.push((i+1, edges))
if not visited[v]:
visited[v] = 1
DFS_sqe.append(v)
st.push((0, graph.out_edges(v)))
else:
# 如果与给的v相关的边都遍历完成后,
# 从图中取一个没有遍历过的顶点(依赖于顶点的表示方式)
try:
v = visited.index(0)
# index方法会找到列表中值为0的元素下标
visited[v] = 1
DFS_sqe.append(v)
st.push((0, graph.out_edges(v)))
except: # 当visited中没有0时,index(0)会抛出错误,
# 即所有的顶点都已经遍历完毕
break
return DFS_sqe
2. 递归式
def my_DFS(graph, v0, d_list = []):
if len(d_list) == graph.vertex_num(): #
# 如果表中的顶点数量与graph顶点数量相同
return d_list
d_list.append(v0)
# 将起始顶点连通的顶点深度遍历
for vj, val in graph.out_edges(v0):
if vj not in d_list:
d_list = my_DFS(graph, vj, d_list)
# 将图中未访问的其他顶点深度遍历
for index in range(graph.vertex_num()):
if index not in d_list:
d_list = my_DFS(graph, index, d_list)
return d_list
暂时没时间详细的更新第7章的内容,只能先占个坑,把遇到的问题说一说,闲下来再更新。