数据结构知识整理 - 遍历图 - 广度优先搜索

版权声明: https://blog.csdn.net/Ha1f_Awake/article/details/85186754

主要内容


图的遍历算法是实现图的其他算法的基础,图的遍历方式有两种:深度优先搜索遍历广度优先搜索遍历

深度优先搜索遍历类似于树的先序遍历(根节点→左子树→右子树),借助了结构以实现递归广度优先搜索遍历则类似于层次遍历,借助于队列结构实现。

因为图的任意两个顶点都有可能存在联系,所以在访问某个顶点后,可能沿着某条路径又会回到访问过的顶点。为了避免同一顶点被访问多次,在遍历图的过程中,必须用一个数组visited[vexnum]记录每个访问过的顶点。

邻接矩阵为存储结构的遍历,时间复杂度为O(n²);以邻接表为存储结构的遍历,时间复杂度为O(n+e)

广度优先搜索

广度优先搜索(Breadth First Search,BFS)遍历类似于树的层次遍历

广度优先的过程与深度优先类似,唯一的区别是广度优先是一层一层地遍历,而不会从某个顶点开始一直往下遍历,直到不符合遍历的条件。

广度优先以横向遍历为先,即访问顶点v1后,顺序访问v1的邻接顶点v2,v3,然后先顺序访问v2的邻接顶点,再顺序访问v3的邻接顶点,如此类推。

深度优先利用结构实现递归,广度优先则需要队列来实现每一层的顺序执行:

(1)v1入队,访问顶点v1,并在visited[vexnum]将顶点v1对应的元素值归TRUE

(2)检查v1的邻接顶点,v2和v3顺序入队

(3)v1出队

(4)访问顶点v2,检查v2的邻接顶点并使它们顺序入队

(5)v2出队,访问顶点v3;

(6)访问顶点v3,检查v3的邻接顶点并使它们顺序入队

(7)之后的入队、出队过程如此类推。

*利用队列“先来先服务”(FCFS)的性质,在编写代码时可以将思路转化为先求队列,再遍历。

邻接矩阵为存储结构的广度优先搜索遍历

int visited[G.vexnum];              /*全局变量和静态变量初始化时会自动被设置为0*/
LinkQueue Q;                        /*定义链队Q*/
InitQueue(Q);                       /*初始化链队Q*/

void AL_EnQueue(LinkQueue &Q, int v1)        /*从顶点v1开始,将所有顶点逐个入队*/
{
    int i = LocateVex(G, v1);

    for(int v2 = 1; v2 <= G.vexnum; v2++)    /*先使v1未被访问的邻接顶点顺序入队*/ 
    {
        int j = LocateVex(G, v2);

        if(G.arcs[i][j] != 0 && visited[j] = FALSE)          
        {
            EnQueue(Q, v2);
            visited[j] = TRUE;               /*标记*/
        }
    }

    for(int v2 = 1; v2 <= G.vexnum; v2++)    /*再在v1的邻接顶点上递归*/ 
    {
        int j = LocateVex(G, v2);

        if(G.arcs[i][j] != 0 && visited[j] = FALSE)          
            AL_QnQueue(Q, v2);        
    }
}

void BFS_AMG(AMGraph &G, int v1)    
{
    EnQueue(Q, v1);                          /*v1入队*/

    int i = LocateVex(G, v1);
    visited[i] = TRUE;

    AL_EnQueue(Q, v1);                       /*所有顶点入队*/

    cout<<GetHead(Q);                        /*访问链队的头结点*/
    DeQueue(Q);                              /*头结点出队*/

}

邻接表为存储结构的广度优先搜索遍历

int visited[G.vexnum];             
LinkQueue Q;                
InitQueue(Q);                  

void AL_EnQueue(LinkQueue &Q, int v1)      
{
    ArcNode *p = G.ALs[v1-1].nextarcnode;

    while(p != NULL)
    {
        int v2 = p->anothervex;
    
        if(visited[v2-1] = FALSE)
            EnQueue(Q, v2); 

        p = p->nextarcnode;
    }               

    while(p != NULL)
    {
        int v2 = p->anothervex;
    
        if(visited[v2-1] = FALSE)
            AL_EnQueue(Q, v2); 

        p = p->nextarcnode;
    }               

}


void BFS_AMG(AMGraph &G, int v1)    
{
    EnQueue(Q, v1);   
                     
    visited[v1-1] = TRUE;

    AL_EnQueue(Q, v1);                   

    cout<<GetHead(Q);                     
    DeQueue(Q);                           

}

​

由深度优先的遍历过程可以得到一棵以起始顶点v1为根结点的树,这棵树称作深度优先生成树

猜你喜欢

转载自blog.csdn.net/Ha1f_Awake/article/details/85186754