图论算法基础-BFS与DFS

注意,这两种算法是图论的基础,很多后续算法都是建立与两者之上,话不多说,让我们进入正题。

宽度优先搜索

思想:假设某个点为图的根节点,把图想象成一颗倒过来的树,每层每层的向下进行搜索,直到遇见正确的结果,当然有人会说图和树是两回事啊,怎么能够这样想象呢?这里就是BFS最重要的一点了,通过栈和vis数组来放入新的点以及记录已经走过的点。
不多说,上图。
图论算法基础-BFS与DFS_第1张图片
首先我们确定a为根节点(在很多题目中根节点为哪个点并不重要)。
先说左图。
1.与a相连的有3条边,a进入栈中,a标记为vis(已访问),开始遍历。
2.栈首是a,通过查找a的边,向下遍历到b,b进入栈中,b标记为已访问。
3.查找a的边,遍历到c ,c进入栈中,c标记为已访问。
4.查找a的边,遍历到d,d进入栈中,d标记为已访问。
5.a的边遍历完毕,a点弹出,此时栈首是b。
6.栈首是b,通过查找b的边,发现无法向下,直接弹出b。
7.栈首是c,通过查找c的边,向下遍历到e,e进入栈中,e标记为已访问。
8.查找c的边,遍历到f,f进入栈中,f标记为已访问。
9.。。。
相信到这里BFS基本的查找方式已经明了,让我们再来模拟另外一个图。
1.与a相连的有2条边,a进入栈中,a标记为vis(已访问),开始遍历。
2.栈首是a,通过查找a的边,向下遍历到b,b进入栈中,b标记为已访问。
3.查找a的边,遍历到c ,c进入栈中,c标记为已访问。
4.a的边遍历完毕,a点弹出,此时栈首是b。
5.栈首是b,通过查找b的边,向下遍历到d,d进入栈中,d标记为已访问。
6.b的边遍历完毕,b点弹出,此时栈首是c。
7.栈首是c,通过查找c的边,这时就出现与左图不同的地方了,c与d相连接了,而这时在这里vis数组就起作用了,检测到d已访问,跳过d直接遍历e。
8.d点同样如此,跳过c点直接遍历f。
9.。。。

我们可以看出,广搜(宽搜)就是一层一层的往下走,所以在一般来说,它搜索到一个正确答案的时候,这个答案一定是离起点最近的的(但是对于加权图来说,第一个搜索到的结果,未必是最优的,应为BFS的顺序只是离起始点的远近)

vector<int>edge[3005]; //记录每个点连接的边
int vis[3005]; //是否访问过
int st;
void bfs(int st)
{
    memset(vis, 0, sizeof(vis));
    queue<int>q;
    q.push(st); //起点进栈
    vis[st] = 1; //起点已访问
    while (!q.empty())
    {
        temp = q.front(); 
        q.pop(); //这里提前弹出了,因为上一行已经记录了栈首,所以这里可以先弹出。
        size = edge[temp].size(); //连接点temp的边的数量
        for (int k = 0; k < size; k++)
        {
            int v = edge[temp][k];//temp的第k条边连接的点赋值v
            if (vis[v])continue;//已访问就跳过
            vis[v] = 1;
            q.push(v);//新点进栈。
        }
    } 
}

深度优先搜索

思想:顾名思义,宽度优先搜索是一层一层慢慢来,而深度优先搜索则是急不可耐的向下冲,对于每一个分支,深搜直接走完,然后回到走尽的前一个分支,继续向下莽。这实质上是一个递归过程。
还是上图。
图论算法基础-BFS与DFS_第2张图片
还是从左图开始
1.查找a的三条边,进入b。
2.发现b已经到尽头,回头至a进入c。
3.查找c的两条边,进入e。
4.。。。

其实DFS很简单,就是一句话,不见黄河不死心,一直往下直到不能走,然后回头。

第二张图我们很明显就发现这个图直接从a开始走到底了。但是有点不容忽视的就是,每次从某个点向下的时候必须给它打上vis标记,不然会出现回头路的情况,也就是可能会造成无线循环,不过在回头的过程中还要把路过的点的vis标志取消掉。(为什么呢?)

然后就是上代码。

vector<int>edge[3005];
int vis[3005];
void dfs(int st)
{
    int size=edge[st].size(); //当前点连接的边数
    for (int i = 0; i <= size ; i++)
    {
        int v=edge[st][i];
        if(vis[v]) continue; //已访问的直接跳过
        vis[i] = 1;
        dfs(v); //进入下一层
        vis[v]=0;
    }
}

以上是一些个人的总结,仅供参考

你可能感兴趣的:(图论算法)