深度优先和广度优先搜索的简单比较实例二 图(无向)的遍历

图(无向)的储存使用邻接矩阵(二维数组模拟)
约定:a[i][j]==1表示i+1点和j+1点有边连接,a[i][j]==0表示没有边连接,a[i][j]==-1表示的是i==j即同一个点

一、深度优先搜索法
“不撞南墙不回头式”的搜索,不从A点开始,先搜索一个与它有边的点,重复此操作,直到找不到点与当前点有边,则返回上一个点,寻找它是否还有其他与它有边且没有被访问过的点,有就继续前面的操作,否则继续放回至上一个点(非常相似与回溯法)。

#include<iostream>
using namespace std;
int num = 0;//记录被访问的点的个数
void dfs(int a[20][20],int book[50],int n,int cur)//a[20][20]数组用于储存图的信息(无向),book[i]==1表示的是点i已被访问,n表示的是图中顶点的个数,cur表示的当前正在被访问的点
{
    num++;//访问的点个数自增
    cout << cur << " ";//输出当前被访问的点
    if (num == n)//访问完了所有点
        return;
    else
    {
        for (int i = 1; i <= n; i++)//对图中的每一个点进行匹配
        {
            if (a[cur][i] == 1 && book[i] == 0)//与当前访问的点有边,且没有被访问过
            {
                if (book[cur]==0)
                    book[cur] = 1;//将当前点置为已被访问了
                dfs(a, book, n, i);//顺着这条线继续寻找与i有边且没有被访问过的点
            }

        }
        return;
    }
}
int main()
{
    int a[20][20], book[50] = { 0 },n, m,t1,t2;//a[20][20]数组用于储存图(无向)的信息,book[i]==1表示的是点i已被访问,n表示的是图中顶点的个数,m表示的是图中的边数,t1,t2是输入边时的顶点参数
    for (int i = 0; i < 20; i++)//初始化邻接矩阵
    {
        for (int j = 0; j < 20; j++)
        {
            if (i == j)//由于点和自身可达但没有边,所有特殊处理置为-1
                a[i][j] = -1;
            else//其余全部置零
                a[i][j] = 0;
        }
    }
    cout << "请输入图中顶点的个数:";
    cin >> n;
    cout << "请输入图中边的条数:";
    cin >> m;
    for (int i = 0; i < m; i++)//输入每条边的两个顶点的信息
    {
        cout << "请输入第 " << i + 1 << "条边的两个顶点:";
        cin >> t1 >> t2;
        while (t1 <= 0 || t1>n || t2 <= 0 || t2 > n)
        {
            cout << "输入的点不在图的范围内!请重新输入!" << endl;
            cout << "请输入第 " << i + 1 << "条边的两个顶点:";
            cin >> t1 >> t2;
        }
        a[t1][t2] = 1;//无向图,若点A有边到B,则B也有边到A
        a[t2][t1] = 1;
    }
    dfs(a, book, n, 1);//从第一个点开始
    cout << endl;
    return 0;
}

二、广度优先搜索法
模拟队列,利用队列的线性和先入先出的特性
即从第一个点开始入队,然后将与它有边且没有被访问过的所有点都入队,然后模拟出队,再将与当前队头有边且没有被访问过的所有点都入队…直到队为空。

#include<iostream>
using namespace std;
int main()
{
    int a[20][20], book[50] = { 0 }, n, m, t1, t2;//a[20][20]数组用于储存图(无向)的信息,book[i]==1表示的是点i已被访问,n表示的是图中顶点的个数,m表示的是图中的边数,t1,t2是输入边时的顶点参数
    int point[30] = { 0 }, *head, *end;//point用于模拟队列,head头指针用于模拟出队,end尾指针用于模拟入队
    head = point;//头指针指向数组的头部
    end = head + 1;//尾指针用于指向存放下一个入队信息的空位置
    for (int i = 0; i < 20; i++)//初始化邻接矩阵
    {
        for (int j = 0; j < 20; j++)
        {
            if (i == j)//由于点和自身可达但没有边,所有特殊处理置为-1
                a[i][j] = -1;
            else//其余全部置零
                a[i][j] = 0;
        }
    }
    cout << "请输入图中顶点的个数:";
    cin >> n;
    cout << "请输入图中边的条数:";
    cin >> m;
    for (int i = 0; i < m; i++)//输入每条边的两个顶点的信息
    {
        cout << "请输入第 " << i + 1 << "条边的两个顶点:";
        cin >> t1 >> t2;
        while (t1 <= 0 || t1>n || t2 <= 0 || t2 > n)
        {
            cout << "输入的点不在图的范围内!请重新输入!" << endl;
            cout << "请输入第 " << i + 1 << "条边的两个顶点:";
            cin >> t1 >> t2;
        }
        a[t1][t2] = 1;//无向图,若点A有边到B,则B也有边到A
        a[t2][t1] = 1;
    }
    *head = 1;
    book[*head] = 1;
    while (head != end)//当两个指针不向碰,即模拟队列为空
    {
        cout << *head << " ";
        for (int i = 1; i <= n; i++)
        {
            if (a[*head][i] == 1 && book[i] == 0)//每一个有边且没有被访问过的点都入队
            {
                book[i] = 1;
                *end = i;//与head有边的入队
                end++;//尾指针后移
            }
        }
        head++;//头指针后移模拟出队
    }
    cout << endl;
    return 0;
}

运行示例及结果:
《深度优先和广度优先搜索的简单比较实例二 图(无向)的遍历》
《深度优先和广度优先搜索的简单比较实例二 图(无向)的遍历》
刚刚入坑算法的萌新,如有错误还望各位路过的大佬多多指点。【抱拳】【抱拳】

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