遍历

我们以前遍历过树,用了几种办法,同样的,这样的思路也可以应用于图。
例如,对于下图:

数据结构:遍历_遍历

用深度优先搜索的办法,我们随便指定一个顶点为初始顶点(因为图种没有第一个顶点这个概念,可以人为指定),如a,先输出a,再看邻接点(b,d,c),我们递归转移到b,对b点,也是先输出,再看它的临界点(d,a),我们转移到d,对d点,还是先输出,再看临界点(b,a)。好家伙,又回到了以前的顶点b和a了,这肯定要避免,所以得有一个是否访问过某个顶点的标志。根据这个标志,我们知道d的邻接点b和a都访问过了,所以递归返回,回到了b点,再看它的下一个邻接点a,也是访问过了,所以递归返回,回到a点,在看a的下一个邻接点d,访问过,再看a的下一个邻接点c,递归转移到c,对c点,也是先输出,再看它的邻接点a,访问过了。至此a的全部邻接点都走完了,整个递归过程结束。
用广度优先搜索的办法,我们也是随便指定一个顶点为初始顶点,如a,我们使用一个列表,先把a入列,并记录已访问过。然后对这个列表循环执行如下操作:
从队列种弹出第一个顶点,先输出a,再看邻接点(b,c,d),把邻接点入列,并记录已访问过。(所以广度优先的访问标志跟深度优先的标志含义有点不同)
代码如下:

class Graph(object):
    def __init__(self,vertex,edge):
        self.MAX_INT=-1
        self.vertex=vertex #顶点,一维数组
        self.vsize=len(self.vertex) 
        self.v=[]
        for i in range(self.vsize):
            self.v.append(i)

        self.edge=edge #边,二维数组
        self.visited=[0]*self.vsize #是否访问过
    def DFS(self,vidx):
        startv = self.vertex[vidx]
        print(startv)
        self.visited[vidx]=1
        adjv=self.edge[vidx]
        for i in range(self.vsize):
            if adjv[i]!=self.MAX_INT and self.visited[i]==0:
                self.DFS(i)
    def BFS(self,vidx):
        que=[]  #访问节点队列
        visiting=[0]*self.vsize
        que.append(vidx)
        visiting[vidx]=1 #访问标志
        while len(que)>0:
            idx=que.pop(0)
            startv = self.vertex[idx]
            print(startv)
            adjv=self.edge[idx]
            for i in range(self.vsize): #增加邻接点
                if adjv[i]!=self.MAX_INT and visiting[i]==0:
                    que.append(i)
                    visiting[i]=1

用一段程序初始化一个图:

def buildGraph():
    MAX_INT=-1
    vertex=['a','b','c','d']
    edge=[[MAX_INT,1,1,1],
          [1,MAX_INT,MAX_INT,1],
          [1,MAX_INT,MAX_INT,MAX_INT],
          [1,1,MAX_INT,MAX_INT]]
    return Graph(vertex,edge)

我这里用的邻接矩阵来存储的数据。
测试一下:

udg=buildGraph()
udg.DFS(0)
udg.BFS(0)

运行结果如下:

a b d c
a b c d

对有向图也是可以的,如:

数据结构:遍历_遍历_02

只要把edge变成:

    edge=[[MAX_INT,MAX_INT,1,1],
          [MAX_INT,MAX_INT,MAX_INT,MAX_INT],
          [MAX_INT,MAX_INT,MAX_INT,MAX_INT],
          [MAX_INT,1,MAX_INT,MAX_INT]]

再次运行就可以了:

a c d b