C++详细讲解图的遍历

 更新时间:2022年05月30日 11:08:24   作者:quicklsleap  
图的遍历是指,从给定图中任意指定的顶点(称为初始点)出发,按照某种搜索方法沿着图的边访问图中的所有顶点,使每个顶点仅被访问一次,这个过程称为图的遍历

图的遍历

要想遍历图,肯定要先储存图啊。

下面我们采用邻接表来存图

也可以看: 点这里

1.用 h 数组保存各个节点能到的第一个节点的编号。开始时,h[i] 全部为 -1。

2.用 e 数组保存节点编号,ne 数组保存 e 数组对应位置的下一个节点所在的索引。

3.用 idx 保存下一个 e 数组中,可以放入节点位置的索引

4.插入边使用的头插法,例如插入:a->b。首先把b节点存入e数组,e[idx] = b。然后 b 节点的后继是h[a],ne[idx] = h[a]。最后,a 的后继更新为 b 节点的编号,h[a] = idx,索引指向下一个可以存储节点的位置,idx ++ 。

模板如下:

//邻接表
const int N = 100010, M = N * 2;
//无向图n条边时,最多2n个idx,因为每条边在邻接表中会出现两次
int h[N], e[M], ne[M], idx;
//n个链表头,e每一个结点的值,ne每一个结点的next指针
void add(int a, int b)//a->b
{//e记录当前点的值(地址->值),ne下一点的地址(地址->地址),h记录指向的第一个点的地址(值->地址)
    e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}//头插法
// 初始化
idx = 0;
memset(h, -1, sizeof h);

图的深度优先遍历(DFS, depth first search)

方法:深度优先搜索的遍历顺序为一条路径走到底然后回溯再走下一条路径这种遍历方法很省内存但是不能一次性给出最短路径或者最优解。 

深度优先遍历的步骤

  1. 访问顶点V
  2. 依次从顶点V的未被访问的邻节点出发,进行深度优先搜索,直至和V有路径相通的顶点都被访问到。
  3. 对于连通图进行遍历时,从一个顶点出发即可访问图中所有的顶点。
  4. 对于非连通图进行遍历时,若图中尚有顶点未被访问,则另选一未曾访问的顶点作为起始点,进行深度优先搜索,直至所有顶点都被访问
// 需要标记数组st[N],  遍历节点的每个相邻的点
void dfs(int u) {
    st[u] = true; // 标记一下,记录为已经被搜索过了,下面进行搜索过程
    for (int i = h[u]; i != -1; i = ne[i]) {
        int j = e[i];
//因为每个节点的编号都是不一样的,所以 用编号为下标 来标记是否被访问过
        if (!st[j]) {
            dfs(j);
        }
    }
}

图的宽度优先遍历(BFS, breadth first search)

方法:从图的某一结点出发,首先依次访问该结点的所有邻接顶点(再按这些顶点被访问的先后次序依次访问与它们相邻接的所有未被访问的顶点,重复此过程,直至所有顶点均被访问为止。

从顶点V出发广度优先搜索的步骤

  1. 访问顶点V
  2. 依次访问顶点V的各个未被访问的临接点(横向访问)
  3. 从V的这些邻接点出发依次访问他们的邻接点,致使“先被访问的顶点的邻接点先于"后访问的顶点的邻接点"被访问(一般可以借助队列实现),直至图中所有已被访问的顶点的邻接点均被访问。
  4. 对于非连通图进行遍历时,若图中尚有顶点未被访问,则另选一未曾访问的顶点作为起始点,进行广度优先搜索,直至所有顶点都被访问

模板及注释

queue<int> q;//借助队列实现
st[1] = true; // 表示1号点已经被遍历过
q.push(1);//1号节点入队列
while (q.size())//对列非空,就一直往后搜索
{
    int t = q.front();//队头出队,找该点能到的点
    q.pop();//遍历完就出队列
    for (int i = h[t]; i != -1; i = ne[i])//遍历所有t节点能到的点,i为节点索引
    {
        int j = e[i];//通过索引i得到t能到的节点编号
        if (!st[j])//如果没有遍历过
        {
            st[j] = true; // 表示点j已经被遍历过
            q.push(j);//节点入队
        }
    }
}

宽度优先搜索BFS的应用

图论算法中大量使用了BFS或类似的算法,其常见的应用如下:

1.求最短路径路径和最小生成树,两个顶点的最短路径是指两个顶点间含有最少顶点的路径,另外最小生成树也可以使用DFS。

2.P2P网络中查找临近的结点,应用场景如P2P文件下载,P2P语音视频通信。

3.搜索引擎的网络爬虫的主要算法之一,DFS也是。

4.社交网络网站,在社交网络中可以搜索k层级以内查找一个人。

5.GPS导航系统,使用BFS查找附近地点等。

6.网络广播,在网络中使用BFS将广播包发送给每个节点。 垃圾回收算法,例如Cheney算法。

7.无向图环或圈检测,BFS和DFS都可以检测无向图的环或圈,有向图环检测只能使用DFS。

8.查找最大流,如下面会谈到的Ford-Fulkerson算法。

9.检测一个图是否是一个二分图,DFS和BFS都可以。

10.路径查找,使用BFS和DFS检测两个顶点是否有一条路径,查找一个顶点到所有可达到的顶点等等。

深度优先遍历DFS的应用

DFS和BFS是图论算法的主要算法,其应用非常多,下面是一些常见例子:

1.无权图中求最短路径和最小生成树。

2.检测环或圈。

3.路径查找,使用DFS查找u到v的一条路径,使用栈stack作为辅助,使用递归算法遇到目标顶点v则入栈,后面陆续入栈,打印内容即为所求路径。

4.拓扑排序:计算机中根据作业之间的关系来调度作业(或根据一定先后顺序优先级等);计算机中的指令调度(先后顺序);重新计算公式值公式单元的计算顺序;逻辑合成;makefile编译任务的执行顺序;数据序列化;编译器中的链接器中解决符号依赖关系。

5.检测一个图是否是二分图。

6.查找有向图的强连通分量,后面会详细讨论其实现算法。

7.解决难题,如迷宫问题。

到此这篇关于C++详细讲解图的遍历的文章就介绍到这了,更多相关C++图的遍历内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C语言非递归算法解决快速排序与归并排序产生的栈溢出

    C语言非递归算法解决快速排序与归并排序产生的栈溢出

    上期我们讲完了排序算法下,不知道小伙伴们有没有发现一个问题,快速排序和归并排序我们都是用递归来实现的,可能有小伙伴会问,如果说数据量很多话,栈区空间会不会不够用呢?这期我们就来解决使用递归实现的排序导致栈溢出如何解决
    2022-04-04
  • C++实现LeetCode(205.同构字符串)

    C++实现LeetCode(205.同构字符串)

    这篇文章主要介绍了C++实现LeetCode(205.同构字符串),本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-07-07
  • C++中replace()函数使用方法汇总

    C++中replace()函数使用方法汇总

    这篇文章主要介绍了C++中replace()函数使用方法汇总,在这篇文章中为大家详细介绍C++ replace()函数的各种应用方式,希望朋友们可以从这里介绍的内容充分掌握这一应用技巧
    2015-11-11
  • 深入理解atoi()与itoa()函数的用法

    深入理解atoi()与itoa()函数的用法

    本篇文章是对atoi()与itoa()函数的用法进行了详细的分析介绍,需要的朋友参考下
    2013-05-05
  • 纯C语言:贪心Prim算法生成树问题源码分享

    纯C语言:贪心Prim算法生成树问题源码分享

    这篇文章主要介绍了贪心Prim算法生成树问题源码,有需要的朋友可以参考一下
    2014-01-01
  • 解决C++全局变量只能初始化不能赋值的问题

    解决C++全局变量只能初始化不能赋值的问题

    今天小编就为大家分享一篇解决C++全局变量只能初始化不能赋值的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-07-07
  • C语言回溯法 实现组合数 从N个数中选择M个数

    C语言回溯法 实现组合数 从N个数中选择M个数

    在平时的算法的题目中,时常会遇到组合数相关的问题,暴力枚举。在N个数中挑选M个数出来。利用for循环也可以处理,但是可拓展性不强,于是写这个模板供以后参考
    2018-08-08
  • 浅析C++字节对齐容易被忽略的两个问题

    浅析C++字节对齐容易被忽略的两个问题

    今天我就和大家分享一下C++字节对齐容易被忽略的两个问题。以下问题也是我实际开发工作中遇到的,如果有不同意见欢迎交流
    2013-07-07
  • C语言实现六边形扫雷游戏的示例代码

    C语言实现六边形扫雷游戏的示例代码

    所谓六边形扫雷,就是没有扫雷模式的消零算法,每一个安全的点都需要单独挖出来,一次显示一个格子,感兴趣的小伙伴可以跟随小编一起了解一下
    2022-12-12
  • 总结C/C++面试中可能会碰到的字符串指针题

    总结C/C++面试中可能会碰到的字符串指针题

    C/C++是最能体现程序员能力的语言之一,其功能强大,在IT行业的各个方面都有大量的应用。下面这篇文章主要介绍了总结了在C/C++面试中可能会碰到的字符串指针题,需要的朋友可以参考借鉴,下面来一起看看吧。
    2017-01-01

最新评论