服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - C++详细讲解图的遍历

C++详细讲解图的遍历

2022-12-13 13:53quicklsleap C/C++

图的遍历是指,从给定图中任意指定的顶点(称为初始点)出发,按照某种搜索方法沿着图的边访问图中的所有顶点,使每个顶点仅被访问一次,这个过程称为图的遍历

图的遍历

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

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

也可以看: 点这里

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 ++ 。

模板如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
//邻接表
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. 对于非连通图进行遍历时,若图中尚有顶点未被访问,则另选一未曾访问的顶点作为起始点,进行深度优先搜索,直至所有顶点都被访问
?
1
2
3
4
5
6
7
8
9
10
11
// 需要标记数组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. 对于非连通图进行遍历时,若图中尚有顶点未被访问,则另选一未曾访问的顶点作为起始点,进行广度优先搜索,直至所有顶点都被访问

模板及注释

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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++图的遍历内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/m0_63233163/article/details/124967221

延伸 · 阅读

精彩推荐
  • C/C++C++实现读取图片长度和宽度

    C++实现读取图片长度和宽度

    这篇文章主要介绍了C++实现读取图片长度和宽度,本文直接给出实现代码,需要的朋友可以参考下...

    C++教程网10092021-02-24
  • C/C++C语言中的强符号和弱符号介绍

    C语言中的强符号和弱符号介绍

    这篇文章主要介绍了C语言中的强符号和弱符号介绍,本文用多个实例来讲解强符号和弱符号,需要的朋友可以参考下...

    C语言教程网12502021-02-23
  • C/C++C++排序算法之插入排序

    C++排序算法之插入排序

    这篇文章主要为大家详细介绍了C++排序算法之插入排序,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    墨上烟雨8832021-08-01
  • C/C++C语言实现图的搜索算法示例

    C语言实现图的搜索算法示例

    这篇文章主要介绍了C语言实现图的搜索算法,结合具体实例形式分析了C语言实现图的定义及搜索相关操作技巧,需要的朋友可以参考下...

    typ20047572021-05-16
  • C/C++C++实现两个有序数组的合并

    C++实现两个有序数组的合并

    这篇文章主要为大家详细介绍了C++实现两个有序数组的合并,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    sigma2beta8602021-08-13
  • C/C++C++编程中的命名空间基本知识讲解

    C++编程中的命名空间基本知识讲解

    这篇文章主要介绍了C++编程中的命名空间基本知识讲解,包括对C++11中内联命名空间新特性的介绍,需要的朋友可以参考下...

    C++教程网9942021-03-22
  • C/C++C++的多态和虚函数你真的了解吗

    C++的多态和虚函数你真的了解吗

    这篇文章主要为大家详细介绍了C++的多态和虚函数,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你...

    山顶夕景4972022-09-22
  • C/C++C++指针学习详解

    C++指针学习详解

    指针在 C\C++ 语言中是很重要的内容,并且和指针有关的内容一向令初学者头大,这篇文章主要给大家介绍了关于C/C++中指针的相关资料,需要的朋友可以参考下...

    TillerB11532022-01-10