《数据结构与算法(Python语言描述)》第7章 图

关于书中深度优先遍历的非递归算法 (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章的内容,只能先占个坑,把遇到的问题说一说,闲下来再更新。

猜你喜欢

转载自blog.csdn.net/qq_39672528/article/details/80240761