BFS(邻接矩阵+队列)和DFS(邻接表+栈)C++实现

5.2 图的遍历

5.2.1 广度优先搜索

概念

广度优先搜索(也称宽度优先搜索,缩写BFS)是连通图的一种遍历算法这一算法也是很多重要的图的算法的原型。Dijkstra单源最短路径算法和Prim最小生成树算法都采用了和宽度优先搜索类似的思想。其别名又叫BFS,属于一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果。换句话说,它并不考虑结果的可能位置,彻底地搜索整张图,直到找到结果为止。基本过程,BFS是从根节点开始,沿着树(图)的宽度遍历树(图)的节点。如果所有节点均被访问,则算法中止。一般用队列数据结构来辅助实现BFS算法。

基本步骤
  1. 给出一连通图,如图,初始化全是白色(未访问);

  1. 搜索起点V1(灰色);

  1. 已搜索V1(黑色),即将搜索V2,V3,V4(标灰);
  2. 对V2,V3,V4重复以上操作;

  1. 直到终点V7被染灰,终止;

模板
/* 
通过邻接矩阵实现BFS
*/

#include <iostream>
#include <queue>
using namespace std;

#define MaxVertexNum 10

struct Graph
{
    
    
    int vertexnum;
    int edgenum;
    bool visit[MaxVertexNum];
    int edgeList[MaxVertexNum][MaxVertexNum];
};

void BuildGraph(Graph *G)
{
    
    
    int start, end;
    cout << "Please enter the number of vertices and edges" << endl;
    cin >> G->vertexnum >> G->edgenum;
    // 图的权重初始化
    for (int i = 0; i < G->vertexnum; i++)
    {
    
    
        G->visit[i] = false;
        for (int j = 0; j < G->vertexnum; j++)
        {
    
    
            G->edgeList[i][j] = 0;
        }
    }
    // 输入权重信息
    for (int i = 0; i < G->edgenum; i++)
    {
    
    
        cout << "Please enter the Start number, end number, weight" << endl;
        cin >> start >> end;
        cin >> G->edgeList[start][end];
        G->edgeList[end][start] = G->edgeList[start][end];
    }
    cout << endl;
}

void BFS(Graph *G)
{
    
    
    queue<int> q;
    G->visit[0] = true;
    q.push(0);
    while (!q.empty())
    {
    
    
        int tmp = q.front();
        q.pop();
        for (int i = 0; i < G->vertexnum; i++)
        {
    
    
            if (G->edgeList[tmp][i] && !G->visit[i])
            {
    
    
                G->visit[i] = true;
                q.push(i);
                cout << i << "Visited" << endl;
            }
        }
    }
}

int main()
{
    
    
    Graph G;
    BuildGraph(&G);
    BFS(&G);
    cout << endl;
    system("pause");
    return 0;
}

/* 
7 9
0 2 1
0 1 1
0 3 1
1 2 1
2 3 1
2 4 1
3 6 1
1 5 1
5 6 1
*/
总结

广度优先搜索就是访问根结点相邻的所有结点,同时相邻的结点被访问后进入队列,然后依次出队,访问所有未访问结点。类似与水波一圈一圈荡开的结构。

5.2.2 深度优先搜索

概念

深度优先搜索属于图算法的一种,是一个针对图和树的遍历算法。深度优先搜索是图论中的经典算法,利用深度优先搜索算法可以产生目标图的相应拓扑排序表,利用拓扑排序表可以方便的解决很多相关的图论问题,如最大路径问题等等。其过程简要来说是对每一个可能的分支路径深入到不能再深入为止,而且每个节点只能访问一次。

基本步骤
  1. 对于下面的树而言,DFS方法首先从根节点1开始

  1. 从stack中访问栈顶的点;

  1. 找出与此点邻接的且尚未遍历的点,进行标记,然后放入stack中,依次进行;

  1. 如果此点没有尚未遍历的邻接点,则将此点从stack中弹出,再按照(3)依次进行;

  1. 直到遍历完整个树,stack里的元素都将弹出,最后栈为空,DFS遍历完成。

模板
/* 
通过邻接表实现DFS
*/

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

#define MaxVertexNum 10

struct EdgeNode
{
    
    
    int adjvex;
    EdgeNode *next;
};

struct VertexNode
{
    
    
    EdgeNode *firstedge;
};

struct Graph
{
    
    
    int vertexnum;
    int edgenum;
    VertexNode vertexList[MaxVertexNum];
    bool visit[MaxVertexNum];
};

void BuildGraph(Graph *G)
{
    
    
    int start, end, weight;
    EdgeNode *newnode;
    cout << "Please enter the number of vertices and edges" << endl;
    cin >> G->vertexnum >> G->edgenum;
    // 图的顶点数据
    for (int i = 0; i < G->vertexnum; i++)
    {
    
    
        G->vertexList[i].firstedge = NULL;
        G->visit[i] = false;
    }
    // 输入权重信息
    for (int i = 0; i < G->edgenum; i++)
    {
    
    
        cout << "Please enter the Start number, end number" << endl;
        cin >> start >> end;
        //start-->end
        newnode = new EdgeNode;
        newnode->adjvex = end;
        newnode->next = G->vertexList[start].firstedge;
        G->vertexList[start].firstedge = newnode;
        // end-->start
        newnode = new EdgeNode;
        newnode->adjvex = start;
        newnode->next = G->vertexList[end].firstedge;
        G->vertexList[end].firstedge = newnode;
    }
}

void Print_Adjacency_Matrix(Graph G)
{
    
    
    for (int i = 0; i < G.vertexnum; i++)
    {
    
    
        cout << i << '\t';
        EdgeNode *p = G.vertexList[i].firstedge;
        while (p)
        {
    
    
            printf("adjvex:%d  ", p->adjvex);
            p = p->next;
        }
        cout << endl;
    }
}

void DFS(Graph *G)
{
    
    
    stack<int> s;
    s.push(0);
    G->visit[0] = true;
    while (!s.empty())
    {
    
    
        int tmp = s.top();
        EdgeNode *p = G->vertexList[tmp].firstedge;
        while (p)
        {
    
    
            if (G->visit[p->adjvex])
            {
    
    
                p = p->next;
            }
            else
            {
    
    
                cout << "-->" << p->adjvex;
                s.push(p->adjvex);
                G->visit[p->adjvex] = true;
                // 找到下一深度的点就不再周边广搜
                break;
            }
            // 周围没有待访问的点,出栈
            if (p == NULL)
            {
    
    
                s.pop();
            }
        }
    }
}

int main()
{
    
    
    Graph G;
    BuildGraph(&G);
    Print_Adjacency_Matrix(G);
    DFS(&G);
    cout << endl;
    system("pause");
    return 0;
}

/*  
9 10
0 1
0 7
1 2
1 4
7 5 
7 8
2 3
4 3
5 3
5 6
*/
总结

深度优先搜索就是一条道走到黑,然后到无路可走的时候回头。所以说最后会回溯所有的点。

猜你喜欢

转载自blog.csdn.net/leoabcd12/article/details/118915640