基于图的深度优先遍历(DFS)与广度优先遍历(BFS)

注意:本篇博文主要注重具体实现,适合于有一定数据结构基础的读者。

初始化:假设给定图G的初态是所有顶点均未曾访问过。

在G中任选一顶点v为初始出发点(源点)。

深度优先遍历:首先访问出发点v,并将其标记为已访问过;然后依次从v出发搜索v的每个邻接点w。若w未曾访问过,则以w为新的出发点继续进行深度优先遍历,直至图中所有和源点v有路径相通的顶点(亦称为从源点可达的顶点)均已被访问为止。依次遍历图中的所有节点,若此时图中仍有未访问的顶点,则另选一个尚未访问的顶点作为新的源点重复上述过程,直至图中所有顶点均已被访问为止。

广度优先遍历:首先访问出发点v,以此遍历v的相邻节点的节点Wn(n=1,2,3,4…),在根据遍历顺序,依次遍历Wn直到与v所有可达的定点都被标记。依次遍历图中的所有节点,若此时图中仍有未访问的顶点,则另选一个尚未访问的顶点作为新的源点重复上述过程,直至图中所有顶点均已被访问为止。

DFS核心代码:

for(i = 0; i < mVexNum; i++){

if(!visited[i])                  //对与i相邻的节点进行深度优先遍历

DFS(i,visited);

}

其中DFS(i, visited)核心代码:

// 遍历该顶点的所有邻接顶点。若是没有访问过,那么继续递归

for(w = firstVertex(i); w >= 0; w = nextVertex(i, w)){

if(!visited[w])

DFS(w,visited);

}

此处对于DFS也可以利用与二叉树的深度优先遍历相似的策略,采用栈的方法操作:

栈S初始化;visited[n]=0;

  访问顶点v;visited[v]=1;顶点v入栈S

  while(栈S非空)

            x=栈S的顶元素(不出栈);

            if(存在并找到未被访问的x的邻接点w)

                    访问w;visited[w]=1;

                    w进栈;

            else

                     x出栈;

BFS核心代码:

    for(i = 0; i < mVexNum; i++){

        if (!visited[i]){

            visited[i] = 1;

            cout << mVexs[i] <<” “;

            queue[rear++] = i;  // 入队列

        }

        while (head != rear) {

            j = queue[head++];  // 出队列

            for (k = firstVertex(j); k >= 0;k = nextVertex(j, k)) //k是为访问的邻接顶点

            {

                if (!visited[k]){

                    visited[k] = 1;

                    cout << mVexs[k]<< ” “;

                    queue[rear++] = k;

                }

            }

        }

}

完整代码:

#include <iomanip>
#include <iostream>
#include <vector>
#include<stack> 
using namespace std;

#define MAX 100
class MatrixUDG {
	private:
        char mVexs[MAX];    // 顶点集合
        int mVexNum;             // 顶点数
        int mEdgNum;             // 边数
        int mMatrix[MAX][MAX];   // 邻接矩阵

    public:
  
        // 创建图(用已提供的矩阵)
        MatrixUDG(char vexs[], int vlen, char edges[][2], int elen);
		~MatrixUDG();

        // 深度优先搜索遍历图
        void DFS();
        // 广度优先搜索(类似于树的层次遍历)
        void BFS();
        // 打印矩阵队列图
        void print();

	private:
        // 读取一个输入字符
        char readChar();
        // 返回ch在mMatrix矩阵中的位置
        int getPosition(char ch);
        // 返回顶点v的第一个邻接顶点的索引,失败则返回-1
        int firstVertex(int v);
        // 返回顶点v相对于w的下一个邻接顶点的索引,失败则返回-1
        int nextVertex(int v, int w);
        // 深度优先搜索遍历图的递归实现
        void DFS(int i, int *visited);

};

 
/*
 * 创建图(用已提供的矩阵)
 *
 * 参数说明:
 *     vexs  -- 顶点数组
 *     vlen  -- 顶点数组的长度
 *     edges -- 边数组
 *     elen  -- 边数组的长度
 */
MatrixUDG::MatrixUDG(char vexs[], int vlen, char edges[][2], int elen)
{
    int i, p1, p2;
    
    // 初始化"顶点数"和"边数"
    mVexNum = vlen;
    mEdgNum = elen;
    // 初始化"顶点"
    for (i = 0; i < mVexNum; i++)
        mVexs[i] = vexs[i];

    // 初始化"边"
    for (i = 0; i < mEdgNum; i++)
    {
        // 读取边的起始顶点和结束顶点
        p1 = getPosition(edges[i][0]);
        p2 = getPosition(edges[i][1]);

        mMatrix[p1][p2] = 1;
        mMatrix[p2][p1] = 1;
    }
}

/* 
 * 析构函数
 */
MatrixUDG::~MatrixUDG() 
{
}

/*
 * 返回ch在mMatrix矩阵中的位置
 */
int MatrixUDG::getPosition(char ch)
{
    int i;
    for(i=0; i<mVexNum; i++)
        if(mVexs[i]==ch)
            return i;
    return -1;
}

/*
 * 读取一个输入字符
 */
char MatrixUDG::readChar()
{
    char ch;

    do {
        cin >> ch;
    } while(!((ch>='a'&&ch<='z') || (ch>='A'&&ch<='Z')));

    return ch;
}
/*
 * 返回顶点v的第一个邻接顶点的索引,失败则返回-1
 */
int MatrixUDG::firstVertex(int v)
{
    int i;

    if (v<0 || v>(mVexNum-1))			//判断定点坐标的合法性 
        return -1;
	
    for (i = 0; i < mVexNum; i++)
        if (mMatrix[v][i] == 1)
            return i;

    return -1;
}

/*
 * 返回顶点v相对于w的下一个邻接顶点的索引,失败则返回-1
 */
int MatrixUDG::nextVertex(int v, int w)
{
    int i;

    if (v<0 || v>(mVexNum-1) || w<0 || w>(mVexNum-1))
        return -1;

    for (i = w + 1; i < mVexNum; i++)
        if (mMatrix[v][i] == 1)
            return i;

    return -1;
}

/*
 * 深度优先搜索遍历图的递归实现
 */
void MatrixUDG::DFS(int i, int *visited)
{
    int w;

    visited[i] = 1;
    cout << mVexs[i] << " ";
    // 遍历该顶点的所有邻接顶点。若是没有访问过,那么继续往下走
    for (w = firstVertex(i); w >= 0; w = nextVertex(i, w))
    {
        if (!visited[w])
            DFS(w, visited);
    }
       
}
/* 
 * 深度优先搜索遍历图
 */
void MatrixUDG::DFS()
{
    int i;
    int visited[MAX];       // 顶点访问标记

    // 初始化所有顶点都没有被访问
    for (i = 0; i < mVexNum; i++)
        visited[i] = 0;

    cout << "DFS: ";
    for (i = 0; i < mVexNum; i++)
    {
        //printf("\n== LOOP(%d)\n", i);
        if (!visited[i])
            DFS(i, visited);
    }
    cout << endl;
}
/*
 * 广度优先搜索(类似于树的层次遍历)
 */
void MatrixUDG::BFS()
{
    int head = 0;
    int rear = 0;
    int queue[MAX];     // 辅组队列
    int visited[MAX];   // 顶点访问标记
    int i, j, k;

    for (i = 0; i < mVexNum; i++)
        visited[i] = 0;

    cout << "BFS: ";
    for (i = 0; i < mVexNum; i++)
    {
        if (!visited[i])
        {
            visited[i] = 1;
            cout << mVexs[i] << " ";
            queue[rear++] = i;  // 入队列
        }
        while (head != rear) 
        {
            j = queue[head++];  // 出队列
            for (k = firstVertex(j); k >= 0; k = nextVertex(j, k)) //k是为访问的邻接顶点
            {
                if (!visited[k])
                {
                    visited[k] = 1;
                    cout << mVexs[k] << " ";
                    queue[rear++] = k;
                }
            }
        }
    }
    cout << endl;
}

/*
 * 打印矩阵队列图
 */
void MatrixUDG::print()
{
    int i,j;

    cout << "Martix Graph:" << endl;
    for (i = 0; i < mVexNum; i++)
    {
        for (j = 0; j < mVexNum; j++)
            cout << mMatrix[i][j] << " ";
        cout << endl;
    }
}


int main()
{
    char vexs[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};
    char edges[][2] = {
        {'A', 'C'}, 
        {'A', 'D'}, 
        {'A', 'F'}, 
        {'B', 'C'}, 
        {'C', 'D'}, 
        {'E', 'G'}, 
        {'F', 'G'}};
    int vlen = sizeof(vexs)/sizeof(vexs[0]);
    int elen = sizeof(edges)/sizeof(edges[0]);
    MatrixUDG* pG;

    // 自定义"图"(输入矩阵队列)	
    //pG = new MatrixUDG();
    // 采用已有的"图"
    pG = new MatrixUDG(vexs, vlen, edges, elen);

    pG->print();   // 打印图
    pG->DFS();     // 深度优先遍历
    pG->BFS();     // 广度优先遍历

    return 0;
}
    原文作者:数据结构之图
    原文地址: https://blog.csdn.net/mingwanganyu/article/details/72513349
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞