连通图里的深度优先和广度优先遍历

article/2025/9/17 4:02:36

从图中的某个顶点出发,按照某种搜索方法沿着图的边访问图中的所有顶点,使得每个顶点仅被访问一次,这个过程称为图的遍历。图的遍历有两种:深度优先遍历和广度优先遍历。
  图分为连通图和非连通图,这里主要讨论连通图的深度、广度优先遍历。
  一、深度优先遍历
  图的深度优先遍历类似于树的先序遍历,它的基本思想是:首先访问指定的起始顶点 v v v, 然后选取与 v v v邻接的未被访问的任意一个顶点 w w w, 访问之,再选取与 w w w邻接的未被访问的任一顶点,访问之。
  重复进行如上的访问,当一个顶点所有邻接顶点都被访问过时,则依次退回到最近被访问过的顶点,若它还有邻接顶点未被访问过,则从这些未被访问的顶点中取出一个顶点开始访问,直到所有的顶点都被访问过为止。
  以邻接表为存储结构的深度优先遍历算法如下(其中, v v v是初始顶点编号,visited[]是一个全局数组,初始时所有元素均为1):

int visited[MAXV];
//连通图的深度优先遍历
void DFS(ALGraph *G,int v){ //G指向某个邻接表,v是起始顶点ArcNode *p;visited[v]=1;                         //已访问,则置1printf("%3d",v);					  //输出被访问顶点的编号p=G->adjlist[v].firstarc;             //p指向顶点v的第一条弧的弧头结点while (p!=NULL)                     {if(visited[p->adjvex]==0)        //若p->adjvex顶点未访问,递归访问它DFS(G,p->adjvex);p=p->nextarc;                   //p指向顶点v的下一条弧的弧头结点}}

二、广度优先遍历
  图的广度优先遍历(又叫宽度优先遍历)类似于树的层次遍历,它的基本思想是:首先访问指定的起始顶点 v v v, 然后选取与 v v v 邻接的全部顶点 w 1 , w 2 , ⋯ w t w_1,w_2, \cdots w_t w1,w2,wt , 再依次访问与 w 1 , w 2 , ⋯ w t w_1,w_2, \cdots w_t w1,w2,wt 邻接的全部顶点(已被访问的顶点除外), 再从这些被访问的顶点出发,逐次访问与它们邻接的全部顶点(已被访问的顶点除外)。依此类推,直到所有的顶点都被访问过为止。
  以邻接表为存储结构,用广度优先搜索遍历图时,需要使用一个队列,对应的算法如下:

//连通图的广度优先遍历
void BFS(ALGraph *G,int v){ //G指向某个邻接表,v是起始顶点ArcNode *p;int queue[MAXV],front=0,rear=0;      //定义循环队列并初始化int visited[MAXV];                   //定义存放结点的访问标志的数组int w,i;for(i=0;i< G->n;i++) visited[i]=0;   //访问标志数组初始化printf("%3d",v);                     //输出被访问顶点的编号visited[v]=1;                        //置已访问标记rear=(rear+1)%MAXV;queue[rear]=v;                      //v进队while (front!=rear)                 //若队列不空时循环{front=(front+1)%MAXV;w=queue[front];                //出队并赋给wp=G->adjlist[w].firstarc;      //找与顶点w邻接的第一个顶点while (p!=NULL){if (visited[p->adjvex]==0)  //若当前邻接顶点未访问{printf("%3d",p->adjvex); //访问相邻顶点visited[p->adjvex]=1;    //置该顶点已被访问的标志rear=(rear+1)%MAXV;      //该顶点进队queue[rear]=p->adjvex;}p=p->nextarc;             //找下一个邻接顶点}}printf("\n");
}

完整代码如下:

//GraphBase.h
typedef int InfoType;
#define MAXV 100       //最大顶点个数//定义邻接矩阵类型
typedef struct{int no;          //顶点编号InfoType info;   //顶点其他信息
}VertexType;       //顶点类型typedef struct{            //图的定义int edges[MAXV][MAXV]; //邻接矩阵int vexnum,arcnum;     //顶点数,弧数VertexType vexs[MAXV]; //存放顶点信息
}MGraph;                   //图的邻接矩阵类型//定义邻接表类型
typedef struct ANode{         //弧的结点结构类型int adjvex;               //该弧的终点位置 struct ANode *nextarc;     //指向下一条弧的指针InfoType info;             //弧的相关信息,用来存放权值
}ArcNode;
typedef int Vertex;
typedef struct Vnode{      //邻接表头结点的类型Vertex data;           //顶点信息ArcNode *firstarc;     //指向第一条弧
}VNode;
typedef VNode AdjList[MAXV]; //AdjList是邻接表类型
typedef struct{AdjList adjlist;     //邻接表int n,e;             //图中顶点数n和边数
}ALGraph;                //图的邻接表类型//主函数.cpp
#include <stdio.h>
#include <malloc.h>
#include "GraphBase.h"
#define INF 32767      //INF表示无穷大,即∞//将邻接矩阵g转换邻接表G
void MatToList(MGraph g,ALGraph *&G){int i,j,n=g.vexnum;                //n为顶点数ArcNode *p;G=(ALGraph *)malloc(sizeof(ALGraph));  for(i=0;i<n;i++)                       //给邻接表中所有头结点的指针域置初值G->adjlist[i].firstarc=NULL;for (i=0;i<n;i++)                    //检查邻接矩阵中的每个元素for (j=n-1;j>=0;j--)if (g.edges[i][j]!=0)        //邻接矩阵的当前元素不为0{p=(ArcNode *)malloc(sizeof(ArcNode));  //创建一个结点*pp->adjvex=j;p->info=g.edges[i][j];p->nextarc=G->adjlist[i].firstarc;   //将*p链接到链表后面G->adjlist[i].firstarc=p;}G->n=n; G->e=g.arcnum;
}//将邻接表G转换为邻接矩阵g
void ListToMat(ALGraph *G,MGraph &g){int i,j,n=G->n;ArcNode *p;for(i=0;i<n;i++)          //g.edges[i][j]赋初值0for(j=0;j<n;j++)g.edges[i][j]=0;for (i=0;i<n;i++){p=G->adjlist[i].firstarc;while(p!=NULL){g.edges[i][p->adjvex]=p->info;p=p->nextarc;}			}g.vexnum=n; g.arcnum=G->e;}//输出邻接矩阵g
void DispMat(MGraph g){int i,j;for (i=0;i<g.vexnum;i++){for(j=0;j<g.vexnum;j++)if(g.edges[i][j]==INF)printf("%3s","∞");elseprintf("%3d",g.edges[i][j]);printf("\n");}}//输出邻接表G
void DispAdj(ALGraph *G){int i;ArcNode *p;for (i=0;i< G->n;i++){p=G->adjlist[i].firstarc;if(p!=NULL) printf("%3d: ",i);while (p!=NULL){printf("%3d",p->adjvex);p=p->nextarc;}printf("\n");}}int visited[MAXV];
//连通图的深度优先遍历
void DFS(ALGraph *G,int v){ //G指向某个邻接表,v是起始顶点ArcNode *p;visited[v]=1;                         //已访问,则置1printf("%3d",v);					  //输出被访问顶点的编号p=G->adjlist[v].firstarc;             //p指向顶点v的第一条弧的弧头结点while (p!=NULL)                     {if(visited[p->adjvex]==0)        //若p->adjvex顶点未访问,递归访问它DFS(G,p->adjvex);p=p->nextarc;                   //p指向顶点v的下一条弧的弧头结点}}//连通图的深度优先遍历(非递归)
void DFS1(ALGraph *G,int v){ArcNode *p;ArcNode *St[MAXV];int top=-1,w,i;for(i=0;i< G->n;i++)visited[i]=0;printf("%3d",v);visited[v]=1;top++;St[top]=G->adjlist[v].firstarc;while (top > -1){	p=St[top]; top--;while (p!=NULL){w=p->adjvex;if (visited[w]==0){printf("%3d",w);visited[w]=1;top++;St[top]=G->adjlist[w].firstarc;break;}p=p->nextarc;}}printf("\n");
}//连通图的广度优先遍历
void BFS(ALGraph *G,int v){ //G指向某个邻接表,v是起始顶点ArcNode *p;int queue[MAXV],front=0,rear=0;      //定义循环队列并初始化int visited[MAXV];                   //定义存放结点的访问标志的数组int w,i;for(i=0;i< G->n;i++) visited[i]=0;   //访问标志数组初始化printf("%3d",v);                     //输出被访问顶点的编号visited[v]=1;                        //置已访问标记rear=(rear+1)%MAXV;queue[rear]=v;                      //v进队while (front!=rear)                 //若队列不空时循环{front=(front+1)%MAXV;w=queue[front];                //出队并赋给wp=G->adjlist[w].firstarc;      //找与顶点w邻接的第一个顶点while (p!=NULL){if (visited[p->adjvex]==0)  //若当前邻接顶点未访问{printf("%3d",p->adjvex); //访问相邻顶点visited[p->adjvex]=1;    //置该顶点已被访问的标志rear=(rear+1)%MAXV;      //该顶点进队queue[rear]=p->adjvex;}p=p->nextarc;             //找下一个邻接顶点}}printf("\n");
}void main()
{int i,j;MGraph g;ALGraph *G;int A[6][6]={{0,5,0,5,5,0},{0,0,4,0,4,0},{0,0,0,0,0,9},{0,0,0,0,0,0},{0,0,5,7,0,7},{0,0,0,0,0,0}};g.vexnum=6; g.arcnum=10;for (i=0;i<g.vexnum;i++)for(j=0;j<g.vexnum;j++)g.edges[i][j]=A[i][j];printf("\n");printf(" 有向图G的邻接矩阵: \n");DispMat(g);G=(ALGraph *)malloc(sizeof(ALGraph));printf(" 图G的邻接矩阵转换为邻接表: \n");MatToList(g,G);DispAdj(G);// 	printf(" 图G的邻接表转换为邻接矩阵: \n");
// 	ListToMat(G,g1);
// 	DispMat(g1);
// 	printf("\n");printf("深度优先遍历:\n");DFS(G,0);printf("\n");printf("深度优先遍历:\n");BFS(G,0);printf("\n");}

效果如下:

图(1) 有向图G的深度优先和广度优先遍历;

  邻接表输出时,由于结点3和结点5的出度都为0,所以是空表即对应的单链表不输出,而结点0、1、2和4的出度都大于0,所以有输出

http://chatgpt.dhexx.cn/article/pFVBU0hI.shtml

相关文章

广度优先算法

广度优先算法 本文主要以介绍算法思想为主这里并没有进行源码实现&#xff0c;但是给出推荐使用的数据结构和主要思想。 首先介绍一下广度优先算法&#xff0c;假设要查找AB两点之间的最短距离&#xff0c;以A为起点B为终点。可以先遍历A的相邻节点&#xff0c;这些节点称之为…

C语言基于邻接表的图的深度优先、广度优先遍历

目录 1 深度优先&#xff08;Depth_First Search&#xff09; 2 广度优先&#xff08;Broadth_First Search&#xff09; 3 基于邻接表的深度优先、广度优先遍历 4 源代码示例 4.1 深度优先 4.2广度优先 假设有无向图G &#xff08;V&#xff0c;E&#xff09;&#xff…

数据结构之深度优先和广度优先遍历

文章目录 图为什么要有图图的常用概念邻接矩阵邻接表图的深度优先遍历深度优先遍历基本思想深度优先遍历算法步骤深度优先算法的代码实现 图的广度优先遍历广度优先遍历基本思想广度优先遍历算法步骤广度优先算法的代码实现图结构完整代码 图 为什么要有图 1)前面我们学了线性…

图的深度优先和广度优先遍历算法

编写一个程序&#xff0c;输出下面带权有向图的邻接表&#xff0c;并根据该邻接表&#xff0c;实现图的遍历运算&#xff0c;具体要求如下&#xff1a; (1)从顶点0开始的深度优先遍历序列(递归算法) (2)从顶点0开始的深度优先遍历序列(非递归算法) (3)从顶点0开始的广度优先遍历…

算法之深度优先、广度优先算法

目录 前言&#xff1a; 搜索算法&#xff1a; 广度优先搜索算法 深度优先搜索算法 问题&#xff1a;如何找出社交网络中某个用户的三度好友关系&#xff1f; 总结&#xff1a; 参考资料&#xff1a; 前言&#xff1a; 图这种数据结构经常用于表示一个社交网络&#x…

广度优先搜索与深度优先搜索

广度优先搜索&#xff08;宽度优先搜索&#xff0c;BFS&#xff09;和深度优先搜索&#xff08;DFS&#xff09;算法的应用非常广泛&#xff0c;本篇文章主要介绍BFS与DFS的原理、实现和应用。 深度优先搜索 图的深度优先搜索(Depth First Search)&#xff0c;和树的先序遍历…

深度优先遍历与广度优先遍历

1、深度优先遍历(Depth First Search, 简称 DFS) 1.1、主要思路 从图中一个未访问的顶点 V 开始&#xff0c;沿着一条路一直走到底&#xff0c;然后从这条路尽头的节点回退到上一个节点&#xff0c;再从另一条路开始走到底…&#xff0c;不断递归重复此过程&#xff0c;直到所…

深度优先与广度优先

深度优先遍历简称DFS&#xff08;Depth First Search&#xff09;&#xff0c;广度优先遍历简称BFS&#xff08;Breadth First Search&#xff09;&#xff0c;它们是遍历图当中所有顶点的两种方式。 深度优先遍历&#xff1a; 选取一个节点开始&#xff0c;沿着一条路一直走…

深度优先遍历(DFS)和广度优先遍历(BFS)

深度优先遍历&#xff08;DFS&#xff09;和广度优先遍历&#xff08;BFS&#xff09; 图的遍历&#xff1a;所谓遍历&#xff0c;即是对结点的访问。一个图有多个结点&#xff0c;如何遍历这些结点&#xff0c;有两种访问策略&#xff1a; 深度优先遍历(Depth First Search, …

深度优先与广度优先的区别!

从深度优先和广度优先两个角度解决同一个问题 题目 从一号顶点开始遍历这个图&#xff0c;使用深度优先搜索和广度优先搜索的2种遍历结果 深度优先遍历的主要思想就是&#xff0c;首先以一个未被访问过的顶点作为起始顶点&#xff0c;沿着当前顶点的边走到未访问过的顶点&…

数据结构:图的遍历--深度优先、广度优先

图的遍历&#xff1a;深度优先、广度优先 遍历 图的遍历是指从图中的某一顶点出发&#xff0c;按照一定的策略访问图中的每一个顶点。当然&#xff0c;每个顶点有且只能被访问一次。 在图的遍历中&#xff0c;深度优先和广度优先是最常使用的两种遍历方式。这两种遍历方式对无…

深度优先搜索与广度优先搜索

算法是作用于具体数据结构之上的&#xff0c;深度优先搜索算法和广度优先搜索算法都是基于“图”这种数据结构的。这是因为&#xff0c;图这种数据结构的表达能力很强&#xff0c;大部分涉及搜索的场景都可以抽象成“图”。 图上的搜索算法&#xff0c;最直接的理解就是&#…

广度优先搜索和深度优先搜索

文章目录 1. 前言2. 广度优先搜索和深度优先搜索1&#xff09;深度优先搜索2&#xff09;广度优先搜索 3. 深度优先搜索算法框架1&#xff09;二叉树深度优先搜索模板2&#xff09;图深度优先搜索模板3&#xff09;二维矩阵深度优先搜索模板 4. 广度优先搜索算法框架1&#xff…

深度优先和广度优先算法

1、深度优先算法 遍历规则&#xff1a;不断地沿着顶点的深度方向遍历。顶点的深度方向是指它的邻接点方向。 最后得出的结果为&#xff1a;ABDECFHG。 Python代码实现的伪代码如下&#xff1a; 2、广度优先算法&#xff1a; 遍历规则&#xff1a; 1&#xff09;先访问完当…

深度优先搜索(DFS)和广度优先搜索(BFS)

代码随想录 深度优先搜索和广度优先搜索&#xff0c;都是图形搜索算法&#xff0c;它两相似&#xff0c;又却不同&#xff0c;在应用上也被用到不同的地方。这里拿一起讨论&#xff0c;方便比较。 先给大家说一下两者大概的区别&#xff1a; 如果搜索是以接近起始状态的程序依次…

算法:深度优先和广度优先(DFS,BFS)

一丶深度优先&#xff08;DFS&#xff09; 深度优先顾名思义: 就是往深的地方优先查找或遍历。 如图二叉树&#xff0c;想遍历树中所有结点可以用中序遍历&#xff0c;前序或后序。如果某一结点还有子结点就会往深处就是往下一结点&#xff0c;一直遍历直到最后一个结点没有子…

【算法】深度优先和广度优先

本文只是总结的相关概念&#xff0c;仅供自己复习&#xff0c;严禁转载&#xff0c;文末附有本文内容涉及的文章链接&#xff0c;请点开链接查看原文&#xff01; &#xff08;一&#xff09;深度优先 深度优先搜索属于图算法的一种&#xff0c;是一个针对图和树的遍历算法&am…

算法:深度优先遍历和广度优先遍历

什么是深度、广度优先遍历 图的遍历是指&#xff0c;从给定图中任意指定的顶点&#xff08;称为初始点&#xff09;出发&#xff0c;按照某种搜索方法沿着图的边访问图中的所有顶点&#xff0c;使每个顶点仅被访问一次&#xff0c;这个过程称为图的遍历。遍历过程中得到的顶点…

ms17010利用失败解决一则

没有反弹得到session并且提示如下&#xff1a; [-] 10.0.131.2:445 - Service failed to start, ERROR_CODE: 216 换了一个payload set payload windows/meterpreter/reverse_tcp set payload windows/x64/meterpreter/bind_tcp 就可以了。 如果遇到Unable to continue with i…

永恒之蓝MS17010复现

MS17010复现 靶机win7&#xff1a;192.168.41.150 攻击kali: 192.168.41.147 扫描 通过auxiliary/scanner/smb/smb_ms17_010模块扫描虚拟机是否存在ms17010漏洞 存在 拿shell 通过exploit/windows/smb/ms17_010_eternalblue 直接exp打&#xff0c;设置好参数和payload,window…