python实现图(基于图的不同存储方式)的深度优先(DFS)和广度(BFS)优先遍历

对于图的遍历操作,一般有两种方法:深度优先遍历和广度优先遍历。

这里我们说的图的遍历是针对连通图而言的,即图中任意的两节点都有一条或多条路径能够相同。

深度优先: 顾名思义,一条路走到黑,选取一个图中的一个节点中作为起始结点,从起始结点开始,不听的访问该节点的下一个结点,直到访问到该节点没有下一个结点与其相连或者与其相连的结点都被访问过,则回退至上一步,看其上一个结点是否还有没被访问的结点,如果有,则继续按照深度优先访问,没有就继续回退,直到确认图中所有的结点都被访问到,则遍历结束。

由此,我们可以看出,在图的深度优先搜索过程中存在一个回溯过程,当访问到的结点没有与它相连的结点,或者与其相连的结点都被访问过时,就需要回溯到上一个结点。由于栈存在先进后出的特点,所以我们可以用栈来实现这个过程。
如果访问到该结点的邻接点未被访问,则将其第一个未被访问的结点添加入栈,直到没有或者所有邻接点都被访问过则进行出栈,没出栈一个元素,都要判断其是否还有未被访问的邻接点,直到栈中所有元素都出栈或者确认图中所有结点都被访问完,则搜索过程结束。

!!!注意:
以下只给出图的深度遍历和广度优先遍历方法,至于图的存储请参考本人博客:
图的三种存储方式(字典形式,邻接矩阵形式,邻接链表形式)

图的邻接表存储,深度优先遍历python实现:

def depth_order(start_node):
    '''
    基于图的邻接链表存储表示,图的深度优先遍历
    :param start_node: 
    :return: 
    '''
    n = int(input("请输入图中结点的个数:"))
    # 实例化图对象
    my_graph = graph()
    # 创建结点
    for i in range(0, n):
        data = input("请输入结点:")
        # 实例化图结点对象
        data = graph_node(data)
        # 将结点添加至图中
        my_graph.add_node(data)
    # print("图中所有顶点:")
    for nn in my_graph.graph:
        print(nn.data, end='\t')
    print(" ")
    # 创建图的邻接链表
    my_graph.create_graph_adjacencyList()
    # 打印图的邻接链表
    my_graph.print_graph_adjacencyList()


    # #遍历图的邻接链表,进行深度遍历
    #定义查找栈
    node_stack = []
    #定义被访问列表
    visited_list = []
    #使用临时列表从图中查找起始结点
    temp_list = []
    for node in my_graph.graph:
        temp_list.append(node.data)
    #如果起始结点在图中,加入被访问列表中,加入查找栈中,
    if my_graph.graph[temp_list.index(start_node)].data == start_node:
        #添加入被访问列表
        visited_list.append(my_graph.graph[temp_list.index(start_node)].data)
        #加入查找栈中
        node_stack.append(my_graph.graph[temp_list.index(start_node)])
        print(my_graph.graph[temp_list.index(start_node)].data)


    #若查找栈不为空,循环查找
    while node_stack != []:
        #以查找栈的元素为起始结点,查找它的链表,找出它的第一个邻接点
        find_node = node_stack[-1]
        #循环查找其邻接链表
        current_node = find_node
        current_node = current_node.next
        #定义标志位,标志其邻接链表中的所有邻接点全部被访问

        allvisited = 1
        while current_node != None:
            #如果该邻接点未被访问过,则说明该节点还有邻接点未被访问,将标志位修改

            if current_node.data not in visited_list:
                allvisited = 0
                break
            current_node = current_node.next

        #如果该节点为None或者该节点的所有邻接点都被访问过,则出栈
        if find_node.next == None or allvisited == 1:
            node_stack.pop()
        #如果该节点不是None或者该节点的所有邻接点没有全被访问,则继续查找其下一个未被访问的邻接点
        else:
            find_node1 = node_stack[-1]
            find_node1 = find_node1.next
            #如果找出该节点的邻接点不为None,继续查找
            while find_node1 != None:
                #如果该节点的邻接点不为None,并且该邻接点未被访问,则继续查找该邻接点的下一个为被访问的邻接点
                if find_node1.data not in visited_list:
                    #若找到的邻接点未被访问,加入查找栈中
                    node_stack.append(find_node1)
                    visited_list.append(find_node1.data)
                    print(find_node1.data)
                    break
                find_node1 = find_node1.next

if __name__ == '__main__':
    start_node = input("请输入深度优先遍历的起始结点:")
    depth_order(start_node)

广度优先: 图的广度优先遍历有些类似于树的层次遍历,从遍历的起始点出发,遍历与该节点相邻的每一个结点,然后再从与该节点相邻接的结点中继续按照广度优先原则访问,直到图中所有的结点都被访问,遍历过程结束。
由此看出,图的广度优先遍历不需要回溯过程,类似于图的层次遍历,可以借助队列来实现图的广度优先遍历。

图的邻接矩阵存储,广度优先遍历python实现:

def breadth_order():
    '''
    基于图的邻接矩阵存储,图的广度优先遍历
    :return: 
    '''
    n = int(input("请输入结点的个数:"))
    #实例化图
    my_graph = graph(n)
    #向图中添加结点
    my_graph1 = my_graph.add_node(n)
    print("图中所有节点:",my_graph1)
    #构造图的邻接矩阵
    my_graph_matrix = my_graph.create_graph_matrix(my_graph1)
    # 打印邻接矩阵
    print("图的邻接矩阵:")
    my_graph.print__graph_matrix(n)

    #构造被访问结点数组,若待访问结点在此数组中,则不需要入队
    visited_node_list = []
    node_list = []
    print("图的广度优先遍历(邻接矩阵存储形式):")
    for i in range(n):
        for j in range(n):
            if my_graph_matrix[i][j] == 1:
                node = my_graph1[i]

                if node not in visited_node_list:
                    visited_node_list.append(node)
                    node_list.append(node)
                    order_node = node_list.pop(0)

                    print(order_node,end='\t')
if __name__ == '__main__':
    breadth_order()

未完待续… …

©️2020 CSDN 皮肤主题: 书香水墨 设计师:CSDN官方博客 返回首页