图的遍历(基础)

article/2025/10/28 19:05:40

目录

一、图的遍历的相关定义

二、深度优先搜索 

(一)深度优先搜索连通子图的基本思想

(二)采用递归的形式说明,则深度优先搜索连通子图的基本思想:                             

(三)树的深度优先遍历

(四)时间复杂度分析 

(五)基于邻接矩阵的深度优先遍历

1. 核心代码

2. 演示

3. 完整代码

4. 结果

5. 非连通图的深度优先遍历

6. 完整代码

7. 结果

(六)基于邻接表的深度优先遍历

1. 核心代码

2. 完整代码

3. 结果

4. Data1.txt数据

三、广度优先搜索

(一)基于邻接矩阵的广度优先遍历

1. 演示

2. 核心代码

3. 完整代码

4. 结果 

(二)基于邻接表的广度优先遍历

1. 核心代码

2. 完整代码

3. 结果


一、图的遍历的相关定义

  •  遍历的定义:从已给的连通图中的某一顶点出发,沿着一些边访遍图中的所有的顶点,且使每个顶点仅被访问一次,就叫做图的遍历,它是图的基本运算。
  • 遍历的实质:找每个邻接点的过程。
  • 图的特点:图中可能存在回路,且图中任一顶点都有可能与其它顶点相通,在访问完某个顶点之后可能会沿着某些边又回到了曾经访问过的顶点。
  • 怎样避免重复访问? 
  •  解决思路:设置辅助数组visited[n],用来标记每个被访问过的顶点。1.初始状态visited[i]为0  ;2.顶点被访问,改visited[i]为1,防止被多次访问 

二、深度优先搜索 

  • 深度优先搜索(Depth-First Search)是指按照深度方向搜索,它类似于树的先根遍历,是树的先根遍历的推广。 

(一)深度优先搜索连通子图的基本思想

  1. 从图中某个顶点v0出发,首先访问v0。                                                                                   
  2. 找出刚访问过的顶点vi的第一个未被访问的邻接点, 然后访问该顶点。以该顶点为新顶点,重复本步骤,直到当前的顶点没有未被访问的邻接点为止。                                                     
  3. 返回前一个访问过的且仍有未被访问的邻接点的顶点, 找出并访问该顶点的下一个未被访问的邻接点,然后执行步骤2 

(二)采用递归的形式说明,则深度优先搜索连通子图的基本思想:                             

  1. 访问出发点v0。
  2. 依次以v0的未被访问的邻接点为出发点,深度优先搜索图,直至图中所有与v0有路径相通的顶点都被访问。 若此时图中还有顶点未被访问,则另选图中一个未被访问的顶点作为起始点,重复上述深度优先搜索过程,直至图中所有顶点均被访问过为止。 

(三)树的深度优先遍历

void PreOrder(TreeNode* R)
{if (R != NULL){visit(R);//访问根结点while (R还有下一个子树T){PreOrder(T);//先根遍历下一棵子树}}
}

(四)时间复杂度分析 

  • 时间复杂度=访问各个结点所需时间+探索各条边所需时间

邻接矩阵存储的图:
访问|V|个顶点需要O(|V|)的时间,查找每个顶点的邻接点都需要O(|V|)的时间,而且总共有|V|个顶点
时间复杂度=O(|V|^{2})

邻接表存储的图:
访问|V|个顶点需要的时间,查找每个顶点的邻接点共需要O(|E|)的时间
时间复杂度=O(|V|+|E|)

(五)基于邻接矩阵的深度优先遍历

1. 核心代码

bool visited[MAXV];//访问标记数组
void DFS(MGraph G, int v);//从第v个顶点开始,深度优先遍历
{visit(v);//访问第v个顶点visited[v] = true;//将第v个顶点设置为已经访问的标记for (int w = FirstNeighbor(G, v); w > 0; w = NextNeighbor(G, v, w)){if (!visited[w])//第w个顶点为第v个顶点尚未访问的邻接点{DFS(G, w);}}
}注意;
int FirstNeighbor(MGraph G, int x);//求图G中顶点x的第一个邻接点,若有则返回顶点号;
//若没有邻接点或图中不存在x,则返回-1
int NextNeighbor(MGraph G, int x, int y);
//假设图G中第y个顶点是第x个顶点的一个邻接点,
//返回除第y个顶点之外,第x个顶点的下一个邻接点的顶点号;若第y个顶点是第x个顶点的最后一个邻接点,则返回-1

2. 演示

3. 完整代码

  •  MGraph.h
#pragma once
#include<iostream>
#include<stdbool.h>
using namespace std;#define MaxVertexNum 100//顶点数目的最大值
//#define INFINITY  100000//宏定义常量“无穷”
#define MAXV 100typedef int VertexType;//顶点的数据类型
//typedef char VertexType;//顶点的数据类型
typedef int EdgeType;//带权图中边上权值的数据类型
typedef struct
{VertexType vexs[MaxVertexNum];//顶点表(存放顶点)EdgeType edges[MaxVertexNum][MaxVertexNum];//邻接矩阵,边表(存放任意两个顶点之间的距离)int n, e;//图的当前顶点数和边数/弧数
}MGraph;void CreatMat(MGraph& G, int A[][MAXV], int n);//由数组A[n][n]生成邻接矩阵G
//生成图的邻接矩阵方法1
void DisMGraph(MGraph& G);//打印void Init(MGraph& G);//初始化,将所有顶点都初始化为没有访问的顶点
void DFS(MGraph G, int v);//从第v个顶点开始,深度优先遍历
int FirstNeighbor(MGraph G, int x);//求图G中顶点x的第一个邻接点,若有则返回顶点号;
//若没有邻接点或图中不存在x,则返回-1
int NextNeighbor(MGraph G, int x, int y);//假设图G中顶点y是顶点x的一个邻接点,
//返回除y之外顶点x的下一个邻接点的顶点号;若y是x的最后一个邻接点,则返回-1
  •  MGraph1.cpp
#include"MGraph.h"void CreatMat(MGraph& G, int A[][MAXV], int n)//由数组A[n][n]生成邻接矩阵G
{G.n = n;G.e = 0;cout << "请依次输入顶点信息:";for (int i = 1; i <= G.n; i++){cin >> G.vexs[i];}for (int i = 0; i < n; i++){for (int j = 0; j < n; j++){G.edges[i + 1][j + 1] = A[i][j];//i+1,j+1是为了从为了从二维数组[1][1]开始存储if (A[i][j] != 0 && A[i][j] != INFINITY){G.e++;//边数加1}}}
}
void DisMGraph(MGraph& G)//遍历打印
{for (int i = 1; i <= G.n; i++){for (int j = 1; j <= G.n; j++){cout << G.edges[i][j] << " ";}cout << endl;}
}bool visited[MAXV];//访问标记数组
void Init(MGraph& G)//初始化
{for (int i = 1; i <= G.n; i++){visited[i] = false;//标记为访问}
}void DFS(MGraph G, int v)//从第v个顶点(下标也是v)开始,深度优先遍历
{cout << G.vexs[v] << " ";//访问第v个顶点visited[v] = true;//将第v个顶点改为已经访问的标记for (int w = FirstNeighbor(G, v); w >= 0; w = NextNeighbor(G, v, w)){if (!visited[w]){DFS(G, w);}}
}int FirstNeighbor(MGraph G, int x)//求图G中第x个顶点的第一个邻接点,若有则返回顶点号;
//若没有邻接点或图中不存在x,则返回-1
{for (int j = 1; j <= G.n; j++){if (G.edges[x][j] == 1)//寻找第x个顶点的第一个邻接点{return j;//返回第x个顶点的第一个邻接点的顶点号}}return -1;
}
int NextNeighbor(MGraph G, int x, int y)//假设图G中第y个顶点是第x个顶点的一个邻接点,
//返回除第y个顶点之外,第x个顶点的下一个邻接点的顶点号;若第y个顶点是第x个顶点的最后一个邻接点,则返回-1
{int i = 1, j = 1;for (int k = y + 1; k <= G.n; k++)//在邻接矩阵第x个顶点所在行//从第y个顶点之后寻找与第x个顶点邻接的顶点{if (G.edges[x][k] == 1){return k;}}return -1;
}
  • Text.cpp
#include"MGraph.h"
int main()
{MGraph G;int A[][MAXV] = { {0,1,0,0,1,0,0,0},{1,0,0,0,0,1,0,0},{0,0,0,1,0,1,1,0},{0,0,1,0,0,0,1,1},{1,0,0,0,0,0,0,0},{0,1,1,0,0,0,1,0}, {0,0,1,1,0,1,0,1},{0,0,0,1,0,0,1,0} };CreatMat(G, A, 8);//方法1cout << "图的邻接矩阵:" << endl;DisMGraph(G);cout << endl;/*cout << G.vexs[4] << endl;cout<<FirstNeighbor(G,2)<<endl;cout << NextNeighbor(G, 2, 1);*/Init(G);//初始化cout << "从2出发的深度优先遍历序列:" << endl;DFS(G, 2);cout << endl;Init(G);//初始化cout << "从3出发的深度优先遍历序列:" << endl;DFS(G, 3);//cout << endl;//Init(G);//初始化//cout << "从1出发的深度优先遍历序列:" << endl;//DFS(G, 5);return 0;
}

4. 结果

5. 非连通图的深度优先遍历

void DFSTraverse(MGraph G)//对图G进行深度优先遍历
{Init(G);//初始化for (int v = 1; v <= G.n; v++){if (!visited[v])//对每个连通分量调用一次DFS{DFS(G, v);}}
}

6. 完整代码

#pragma once
#include<iostream>
#include<stdbool.h>
using namespace std;#define MaxVertexNum 100//顶点数目的最大值
//#define INFINITY  100000//宏定义常量“无穷”
#define MAXV 100typedef int VertexType;//顶点的数据类型
//typedef char VertexType;//顶点的数据类型
typedef int EdgeType;//带权图中边上权值的数据类型
typedef struct
{VertexType vexs[MaxVertexNum];//顶点表(存放顶点)EdgeType edges[MaxVertexNum][MaxVertexNum];//邻接矩阵,边表(存放任意两个顶点之间的距离)int n, e;//图的当前顶点数和边数/弧数
}MGraph;void CreatMat(MGraph& G, int A[][MAXV], int n);//由数组A[n][n]生成邻接矩阵G
//生成图的邻接矩阵方法1
void DisMGraph(MGraph& G);//打印void Init(MGraph& G);//初始化,将所有顶点都初始化为没有访问的顶点
void DFS(MGraph G, int v);//从第v个顶点开始,深度优先遍历
int FirstNeighbor(MGraph G, int x);//求图G中顶点x的第一个邻接点,若有则返回顶点号;
//若没有邻接点或图中不存在x,则返回-1
int NextNeighbor(MGraph G, int x, int y);
//假设图G中第y个顶点是第x个顶点的一个邻接点,
//返回除第y个顶点之外,第x个顶点的下一个邻接点的顶点号;若第y个顶点是第x个顶点的最后一个邻接点,则返回-1
void DFSTraverse(MGraph G);//对图G进行深度优先遍历(图G可以是非连通图)

#include"MGraph.h"void CreatMat(MGraph& G, int A[][MAXV], int n)//由数组A[n][n]生成邻接矩阵G
{G.n = n;G.e = 0;cout << "请依次输入顶点信息:";for (int i = 1; i <= G.n; i++){cin >> G.vexs[i];}for (int i = 0; i < n; i++){for (int j = 0; j < n; j++){G.edges[i + 1][j + 1] = A[i][j];//i+1,j+1是为了从为了从二维数组[1][1]开始存储if (A[i][j] != 0 && A[i][j] != INFINITY){G.e++;//边数加1}}}
}
void DisMGraph(MGraph& G)//遍历打印
{for (int i = 1; i <= G.n; i++){for (int j = 1; j <= G.n; j++){cout << G.edges[i][j] << " ";}cout << endl;}
}bool visited[MAXV];//访问标记数组
void Init(MGraph& G)//初始化
{for (int i = 1; i <= G.n; i++){visited[i] = false;//标记为访问}
}void DFS(MGraph G, int v)//从第v个顶点(下标也是v)开始,深度优先遍历
{cout << G.vexs[v] << " ";//访问第v个顶点visited[v] = true;//将第v个顶点改为已经访问的标记for (int w = FirstNeighbor(G, v); w >= 0; w = NextNeighbor(G, v, w)){if (!visited[w]){DFS(G, w);}}
}int FirstNeighbor(MGraph G, int x)//求图G中第x个顶点的第一个邻接点,若有则返回顶点号;
//若没有邻接点或图中不存在x,则返回-1
{for (int j = 1; j <= G.n; j++){if (G.edges[x][j] == 1)//寻找第x个顶点的第一个邻接点{return j;//返回第x个顶点的第一个邻接点的顶点号}}return -1;
}
int NextNeighbor(MGraph G, int x, int y)//假设图G中第y个顶点是第x个顶点的一个邻接点,
//返回除第y个顶点之外,第x个顶点的下一个邻接点的顶点号;若第y个顶点是第x个顶点的最后一个邻接点,则返回-1
{int i = 1, j = 1;for (int k = y + 1; k <= G.n; k++)//在邻接矩阵第x个顶点所在行//从第y个顶点之后寻找与第x个顶点邻接的顶点{if (G.edges[x][k] == 1){return k;}}return -1;
}void DFSTraverse(MGraph G)//对图G进行深度优先遍历
{Init(G);//初始化for (int v = 1; v <= G.n; v++){if (!visited[v])//对每个连通分量调用一次DFS{DFS(G, v);}}
}

7. 结果

(六)基于邻接表的深度优先遍历

 

1. 核心代码

int visited[MAXV] = { 0 };
void DFSA(AGraph* G, int i)//邻接表的深度优先算法,i表示从第i个顶点开始深度优先遍历
{ArcNode* p;visited[i] = 1;cout << G->adjlist[i].data<<" ";//访问顶点vip = G->adjlist[i].firstarc;//取vi边表的头指针while (p)//寻找vi的邻接点vj{if (!visited[p->adjvex])//若vj尚且未被访问,则以vj为出发点向纵深搜索{DFSA(G, p->adjvex);}p = p->nextarc;//找vi的下一个邻接点}
}

2. 完整代码

  • AGraph.h 
#pragma once
#include<iostream>
#include<stdbool.h>
using namespace std;//输入流的头文件
#include <cstring>           
#include <io.h>    
#include <fstream>
#define txtRows       8 //txt行数
#define txtCols       8 //txt列数typedef int ElemType;
typedef int InfoType;
#define MAXV 100
#define INF 10000
typedef struct ANode//边结点类型
{int adjvex;//该边的终点位置struct ANode* nextarc;//指向一下条边的指针InfoType info;//该边的相关信息,如带权图可存放权重
}ArcNode;typedef struct Vode//表头结点的类型
{ElemType data;//顶点信息ArcNode* firstarc;//指向第一条边
}VNode;typedef VNode AdjList[MAXV]; //AdjList是邻接表类型
typedef struct
{AdjList adjlist;//邻接表(表头结点组成一个数组)int n, e;//定义顶点数和边数
}AGraph;//图的领接表类型void CreatAdj(AGraph*& G, int A[][MAXV], int n);//由数组A[n][n]生成邻接矩阵G
//生成图的邻接表
void DisAdj(AGraph* G);//打印
void DFSA(AGraph* G, int i);//邻接表的深度优先算法,i表示从第i个顶点开始深度优先遍历
  •  AGraph1.cpp
#include"AGraph.h"void CreatAdj(AGraph*& G, int A[][MAXV], int n)//由数组A[n][n]生成邻接表G
{G = (AGraph*)malloc(sizeof(AGraph));//分配邻接表空间G->n = n;G->e = 0;cout << "请依次输入顶点信息:";for (int i = 1; i <= n; i++)//邻接表的所有表头结点的指针域都设置为空{cin >> G->adjlist[i].data;G->adjlist[i].firstarc = NULL;}ArcNode* p = NULL;for (int i = 0; i < n; i++){for (int j = n - 1; j >= 0; j--){if (A[i][j] != 0 && A[i][j] != INF)//存在一条边{p = (ArcNode*)malloc(sizeof(ArcNode));//创建一个边结点pp->adjvex = j+1;//该边的终点p->info = A[i][j];//该边的权重p->nextarc = G->adjlist[i+1].firstarc;//将新边结点p用头插法插入到顶点Vi的边表头部G->adjlist[i+1].firstarc = p;G->e++;//对于无向图,边数需要除以2}}}
}void DisAdj(AGraph* G)//打印
{ArcNode* p;for (int i = 1; i <= G->n; i++){cout << "[" << i << "]" << G->adjlist[i].data;p = G->adjlist[i].firstarc;//找到顶点i的第一个邻接点while (p != NULL){cout << "->";cout << p->adjvex;p = p->nextarc;//找到下一个邻接点}cout << endl;}
}int visited[MAXV] = { 0 };
void DFSA(AGraph* G, int i)//邻接表的深度优先算法,i表示从第i个顶点开始深度优先遍历
{ArcNode* p;visited[i] = 1;cout << G->adjlist[i].data<<" ";//访问顶点vip = G->adjlist[i].firstarc;//取vi边表的头指针while (p)//寻找vi的邻接点vj{if (!visited[p->adjvex])//若vj尚且未被访问,则以vj为出发点向纵深搜索{DFSA(G, p->adjvex);}p = p->nextarc;//找vi的下一个邻接点}
}
  •  Text.cpp
#include"AGraph.h"
int main()
{int A[MAXV][MAXV];FILE* fp;errno_t err = fopen_s(&fp, "C:\\Users\\86173\\Desktop\\Data1.txt", "r");//注意:Data.txt的属性中显示的是C:\Users\86173\Desktop//需要将单斜杠变双斜杠,双斜杠变四斜杠if (fp == NULL){cout << "文件读取错误!";return -1;}for (int i = 0; i < txtRows; i++){for (int j = 0; j < txtCols; j++){fscanf_s(fp, "%d", &A[i][j]);/*每次读取一个数,fscanf_s函数遇到空格或者换行结束*/}fscanf_s(fp, "\n");}fclose(fp);AGraph* G;CreatAdj(G, A, 8);cout << "邻接表形式:" << endl;DisAdj(G);cout << endl<<"邻接表的深度遍历序列为:";DFSA(G, 2);return 0;
}

3. 结果

4. Data1.txt数据

0 1 0 0 1 0 0 0
1 0 0 0 0 1 0 0
0 0 0 1 0 1 1 0
0 0 1 0 0 0 1 1
1 0 0 0 0 0 0 0
0 1 1 0 0 0 1 0
0 0 1 1 0 1 0 1
0 0 0 1 0 0 1 0

三、广度优先搜索

  • 广度优先搜索(Breadth - First Search)是指照广度方向搜索,它类似于树的层次遍历,是树的按层次遍历的推广。
  • 广度优先搜索的基本思想是:
  1. 访问顶点v
  2. 依次访问顶点v的各个未被访问的邻接点
  3. 分别从这些邻接点出发,依次访问它们的邻接点,并使“先被访问的顶点的邻接点”先于”后被访问的顶点的邻接点”被访问
  4. 若此时图中尚有顶点未被访问,则任选其一为起点,重复,直至图中所有顶点都被访问到

(一)基于邻接矩阵的广度优先遍历

1. 演示

2. 核心代码

void BFS(MGraph* G, int v)//从v出发,广度优先遍历图G
{visit(v);//访问vvisited[v] = true;//对v做已访问的标记EnQueue(Q, v);//顶点v入队列Qwhile (!isEmpty(Q)){DeQueue(Q, v);//顶点v出队列for (int w = FirstNeighbor(G, v); w >= 0; w = NextNeighbor(G, v, w)){if (!visited[w]){visit(w);//访问顶点wvisited[w] = true;EnQueue(Q, w);//顶点w出队}}}
}

3. 完整代码

  • MGraph.h
#pragma once
#include<iostream>
#include<stdbool.h>
using namespace std;#include<string>
#include<io.h>
#include<fstream>
#define txtRows 8 //行数
#define txtCols 8  //列数#define MAXSIZE 10
#define MaxVertexNum 100//顶点数目的最大值
//#define INFINITY  100000//宏定义常量“无穷”
#define MAXV 100
typedef int VertexType;//顶点的数据类型
typedef int EdgeType;//带权图中边上权值的数据类型
typedef struct
{VertexType vexs[MaxVertexNum];//顶点表(存放顶点)EdgeType edges[MaxVertexNum][MaxVertexNum];//邻接矩阵,边表(存放任意两个顶点之间的距离)int n, e;//图的当前顶点数和边数/弧数
}MGraph;void CreatMat(MGraph& G, int A[][MAXV], int n);//由数组A[n][n]生成邻接矩阵G
void DisMGraph(MGraph& G);//遍历打印
int FirstNeighbor(MGraph G, int x);//求图G中第x个顶点的第一个邻接点,若有则返回顶点号;
//若没有邻接点或图中不存在x,则返回-1
int NextNeighbor(MGraph G, int x, int y);//假设图G中第y个顶点是第x个顶点的一个邻接点,
//返回除第y个顶点之外,第x个顶点的下一个邻接点的顶点号;若第y个顶点是第x个顶点的最后一个邻接点,则返回-1//void BFS(MGraph G, int v);//从顶点v出发,广度优先遍历
void BFS(MGraph G, int i);//从第i个顶点出发,广度优先遍历
  •  MGraph1.cpp

#include"AGraph.h"void CreatMat(MGraph& G, int A[][MAXV], int n)//由数组A[n][n]生成邻接矩阵G
{G.n = n;G.e = 0;cout << "请依次输入顶点信息:";for (int i = 1; i <= G.n; i++){cin >> G.vexs[i];}for (int i = 0; i < n; i++){for (int j = 0; j < n; j++){G.edges[i + 1][j + 1] = A[i][j];//i+1,j+1是为了从为了从二维数组[1][1]开始存储if (A[i][j] != 0 && A[i][j] != INFINITY){G.e++;//边数加1}}}
}void DisMGraph(MGraph& G)//遍历打印
{for (int i = 1; i <= G.n; i++){for (int j = 1; j <= G.n; j++){cout << G.edges[i][j] << " ";}cout << endl;}
}int visited[MAXV] = { 0 };int FirstNeighbor(MGraph G, int x)//求图G中第x个顶点的第一个邻接点,若有则返回顶点号;
//若没有邻接点或图中不存在x,则返回-1
{for (int j = 1; j <= G.n; j++){if (G.edges[x][j] == 1)//寻找第x个顶点的第一个邻接点{return j;//返回第x个顶点的第一个邻接点的顶点号}}return -1;
}
int NextNeighbor(MGraph G, int x, int y)//假设图G中第y个顶点是第x个顶点的一个邻接点,
//返回除第y个顶点之外,第x个顶点的下一个邻接点的顶点号;若第y个顶点是第x个顶点的最后一个邻接点,则返回-1
{int i = 1, j = 1;for (int k = y + 1; k <= G.n; k++)//在邻接矩阵第x个顶点所在行//从第y个顶点之后寻找与第x个顶点邻接的顶点{if (G.edges[x][k] == 1){return k;}}return -1;
}void BFS(MGraph G, int i)//从第i个顶点出发,广度优先遍历
{VertexType Qu[MAXV];//定义循环队列int front = 0, rear = 0;//初始化cout << G.vexs[i] << " ";//访问第i个顶点visited[i] = 1;//第i个顶点标记为已访问Qu[rear] = G.vexs[i];//第i个顶点入队rear = (rear + 1) % MAXSIZE;while (front != rear){VertexType w = Qu[front];front = (front + 1) % MAXSIZE;int m=0;for (int k=1; k <= G.n; k++){if (G.vexs[k] == w){m = k;break;}}for (int w = FirstNeighbor(G, m); w > 0; w = NextNeighbor(G, m, w)){if (!visited[w])//第w个顶点为第v个顶点尚且未访问的顶点{cout << G.vexs[w] << " ";visited[w] = 1;Qu[rear] = G.vexs[w];//第w个顶点入队rear = (rear + 1) % MAXSIZE;}}}
}
  • Text.cpp 
#include"AGraph.h"
int main()
{int A[MAXV][MAXV];FILE* fp;errno_t err = fopen_s(&fp,"C:\\Users\\86173\\Desktop\\Data1.txt","r");if (fp == NULL){return -1;}for (int i = 0; i < txtRows; i++){for (int j = 0; j < txtCols; j++){fscanf_s(fp,"%d", & A[i][j]);}fscanf_s(fp, "\n");}fclose(fp);MGraph G;CreatMat(G, A, 8);cout << "邻接矩阵形式:" << endl;DisMGraph(G);cout << "从第2个顶点出发广度优先遍历顺序为:" << endl;BFS(G, 2);return 0;}

4. 结果 

(二)基于邻接表的广度优先遍历

1. 核心代码

void BFS(AGraph* G, int v);//从顶点v出发,广度优先遍历
void BFS2(AGraph* G, int i);//从第i个顶点出发,广度优先遍历int visited[MAXV] = { 0 };
void BFS(AGraph* G, int v)//从顶点v出发,广度优先遍历
{ArcNode* p = NULL;int Qu[MAXV];int front = 0, rear = 0;int w;cout << v << " ";visited[v] = 1;Qu[rear] = v;rear = (rear + 1) % MAXSIZE;while (front != rear){w = Qu[front];front = (front + 1) % MAXSIZE;p = G->adjlist[w].firstarc;while (p != NULL){if (visited[p->adjvex] == 0){cout << p->adjvex << " ";visited[p->adjvex] = 1;Qu[rear] = p->adjvex;rear = (rear + 1) % MAXSIZE;}p = p->nextarc;}}
}
void BFS2(AGraph* G, int i)//从第i个顶点出发,广度优先遍历
{ArcNode* p;ElemType Qu[MAXV];//定义循环队列int front = 0, rear = 0;//初始化cout << G->adjlist[i].data << " ";//访问第i个顶点visited[i] = 1;//第i个顶点标记为已访问Qu[rear] = G->adjlist[i].data;//第i个顶点入队rear = (rear + 1) % MAXSIZE;while (front != rear){ElemType w = Qu[front];front = (front + 1) % MAXSIZE;int m=0;for (int k=1; k <= G->n; k++){if (G->adjlist[k].data == w){m = k;break;}}p = G->adjlist[m].firstarc;while (p != NULL){if (visited[p->adjvex] == 0){cout << G->adjlist[p->adjvex].data << " ";visited[p->adjvex] = 1;Qu[rear] = G->adjlist[p->adjvex].data;rear = (rear + 1) % MAXSIZE;}p = p->nextarc;}}
}

2. 完整代码

  • AGraph.h 
#pragma once
#include<iostream>
#include<stdbool.h>
using namespace std;#include<string>
#include<io.h>
#include<fstream>
#define txtRows 8 //行数
#define txtCols 8  //列数#define MAXV 100//最多顶点个数
#define INF 10000//“无穷”
#define MAXSIZE 6
typedef int ElemType;
typedef int InfoType;
typedef struct ANode//边结点类型
{int adjvex;InfoType info;struct ANode* nextarc;
}ArcNode;typedef struct Vode//表头结点类型
{ElemType data;//顶点信息ArcNode* firstarc;
}VNode;typedef VNode Adjlist[MAXV];//Adjlist是邻接表类型typedef struct
{int n, e;Adjlist adjlist;
}AGraph;void CreatAdj(AGraph*& G, int A[][MAXV], int n);//创建邻接表
void DisAdj(AGraph* G);//打印void BFS(AGraph* G, int v);//从顶点v出发,广度优先遍历
void BFS2(AGraph* G, int i);//从第i个顶点出发,广度优先遍历
  •  AGraph1.cpp
#include"AGraph.h"
void CreatAdj(AGraph*& G, int A[][MAXV], int n)
{G = (AGraph*)malloc(sizeof(AGraph));G->n = n;G->e = 0;cout << "请依次输入各顶点:" << endl;for (int i = 1; i <= G->n; i++){cin >> G->adjlist[i].data;G->adjlist[i].firstarc = NULL;}for (int i = 0; i < G->n; i++){for (int j = (G->n)-1; j >=0; j--){if (A[i][j] != 0 && A[i][j] != INF){ArcNode* p = (ArcNode*)malloc(sizeof(ArcNode));p->info = A[i][j];p->adjvex = j + 1;p->nextarc = G->adjlist[i + 1].firstarc;//头插G->adjlist[i + 1].firstarc = p;G->e++;}}}
}void DisAdj(AGraph* G)//打印
{ArcNode* p;for (int i = 1; i <= G->n; i++){cout << "[" << i << "]" << G->adjlist[i].data;p = G->adjlist[i].firstarc;//p为第i个顶点的第一个邻接点while (p != NULL){cout << "->";cout << p->adjvex;p = p->nextarc;}cout << endl;}
}int visited[MAXV] = { 0 };
void BFS(AGraph* G, int v)//从顶点v出发,广度优先遍历
{ArcNode* p = NULL;int Qu[MAXV];int front = 0, rear = 0;int w;cout << v << " ";visited[v] = 1;Qu[rear] = v;rear = (rear + 1) % MAXSIZE;while (front != rear){w = Qu[front];front = (front + 1) % MAXSIZE;p = G->adjlist[w].firstarc;while (p != NULL){if (visited[p->adjvex] == 0){cout << p->adjvex << " ";visited[p->adjvex] = 1;Qu[rear] = p->adjvex;rear = (rear + 1) % MAXSIZE;}p = p->nextarc;}}
}
void BFS2(AGraph* G, int i)//从第i个顶点出发,广度优先遍历
{ArcNode* p;ElemType Qu[MAXV];//定义循环队列int front = 0, rear = 0;//初始化cout << G->adjlist[i].data << " ";//访问第i个顶点visited[i] = 1;//第i个顶点标记为已访问Qu[rear] = G->adjlist[i].data;//第i个顶点入队rear = (rear + 1) % MAXSIZE;while (front != rear){ElemType w = Qu[front];front = (front + 1) % MAXSIZE;int m=0;for (int k=1; k <= G->n; k++){if (G->adjlist[k].data == w){m = k;break;}}p = G->adjlist[m].firstarc;while (p != NULL){if (visited[p->adjvex] == 0){cout << G->adjlist[p->adjvex].data << " ";visited[p->adjvex] = 1;Qu[rear] = G->adjlist[p->adjvex].data;rear = (rear + 1) % MAXSIZE;}p = p->nextarc;}}
}
  •  Text.cpp
#include"AGraph.h"
int main()
{int A[MAXV][MAXV];FILE* fp;errno_t err = fopen_s(&fp,"C:\\Users\\86173\\Desktop\\Data1.txt","r");if (fp == NULL){return -1;}for (int i = 0; i < txtRows; i++){for (int j = 0; j < txtCols; j++){fscanf_s(fp,"%d", & A[i][j]);}fscanf_s(fp, "\n");}fclose(fp);AGraph *G;CreatAdj(G, A, 8);DisAdj(G);cout << "从第2个顶点出发广度优先遍历顺序为:" << endl;BFS2(G, 2);return 0;}

3. 结果


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

相关文章

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

1.概念 图的遍历操作是从图中某一顶点出发&#xff0c;对图中所有顶点访问一次且仅访问一次 &#xff08;1&#xff09;在图中&#xff0c;遍历的起始顶点是编号最小的顶点 &#xff08;2&#xff09;某个起点到达不了所有顶点&#xff0c;则多次调用访问所有顶点 &#xf…

数据结构 第六章 图——图的遍历

6.5 图的遍历 在前面我们知道&#xff0c;树是一种非线性结构&#xff0c;为了方便它在计算机中的存储&#xff0c;对树进行遍历使它线性化。 而图同样也是一种非线性结构&#xff0c;但是图又是一种不同于树的多对多结构&#xff0c;所以在前面我们将其转换为了多个一对多的结…

数据结构——图(图的遍历)

图的遍历 图的遍历深度优先遍历&#xff08;DFS&#xff09;DFS算法效率分析深度优先遍历算法的实现广度优先搜索遍历&#xff08;BFS&#xff09;BFS算法效率分析DFS与BFS算法比较 图的遍历 遍历定义&#xff1a;从已给的连通图中某一顶点出发&#xff0c;沿着一些边访遍图中所…

图的遍历 (深度优先遍历和广度优先遍历)

一. 什么是深度优先遍历 深度优先遍历可定义如下&#xff1a;首先访问出发点v&#xff0c;并将其标记为已访问过&#xff1b;然后依次从v出发搜索v的每个邻接点w。若w未曾访问过&#xff0c;则以w为新的出发点继续进行深度优先遍历&#xff0c;直至图中所有和源点v有路径相通的…

图的遍历

图的遍历 介绍 是从图的某一顶点出发&#xff0c;按照某种搜索方式对图中所有顶点访问一次且仅一次。图的遍历可以解决很多搜索问题&#xff0c;在实际中应用非常广泛。图的遍历根据搜索方式的不同&#xff0c;分为广度优先搜索和深度优先搜索。 一.深度优先遍历 1.1介绍 深…

视频和图片合成软件,简单快速合成视频和图片

怎么把小视频和图片合成起来&#xff1f;有简单好上手的教程吗&#xff1f;今天就教大家简单几步&#xff0c;把视频和图片合成为照片视频。先看看用数码大师合成视频和图片的效果截图&#xff1a; 第一步&#xff1a;把图片一次性导入&#xff0c;为照片配上文字 点击“添加…

多张图片怎么合成gif?

多张图片怎么合成gif&#xff1f;gif动图是我们比较熟悉的一种网络聊天表情包&#xff0c;通常都是由图片或者视频转换而来的。很多小伙伴会选择用PS来制作GIF动图&#xff0c;但并不是所有小伙伴都会使用PS&#xff0c;所以一个自动简单&#xff0c;可以将图片或者视频直接转换…

android将图片做成视频播放,如何把图片做成视频【图文教程】

教你怎么将手机拍摄的一张张图片整合转换成视频播放更唯美。下面以直走婚纱mv电子相册为例。 安装好软件&#xff0c;先运行绿化程序&#xff0c;然后再运行软件&#xff0c;详情请参看使用说明txt文档。打开之后&#xff0c;有两个模式供你选择&#xff0c;左边是标准模式、右…

php把图片合成视频,如何把照片做成视频 照片音乐视频制作 并插入几段短视频片段...

如何把照片制作成视频&#xff1f;相信大家都已经有所耳闻了&#xff0c;把平时手机或者相机上拍摄的照片&#xff0c;还有拍摄的视频都可以合起来&#xff0c;再添加背景音乐就成了一个非常有纪念价值的视频了。然而已经不是只有照片和音乐的视频了&#xff0c;整个视频全是照…

视频转图片-人脸识别-合成视频

视频转图片-人脸识别-合成视频 代码&#xff1a; import cv2 import os,sys import numpy as npface_xml cv2.CascadeClassifier(r"C:\Users\lenovo\Desktop\python\jiqixuexi\haarcascade_frontalface_default.xml") eye_xml cv2.CascadeClassifier(r"C:\U…

怎样用计算机合并视频,电脑视频合并软件 , 怎样把多个视频合成为一个

昨天小编在搜梁博的歌曲《表态》的视频时(这首歌小编觉得真的很好听推荐下)在一个剪辑视频发现他将梁博在某综艺唱的歌曲全都剪辑在视频里。这里就运用到了一个剪辑视频知识&#xff0c;合并视频。既然看到小编就准备跟大家伙讲讲这个视频剪辑内容。如何把多个视频合并在一个视…

php合成视频特效,视频合并加转场效果

热爱视频后期剪辑的朋友都会知道&#xff0c;在视频的后期制作过程中&#xff0c;常见操作中就有视频合并这一项&#xff0c;及在视频之间加入转场效果&#xff0c;为影视编辑作品带来绚丽多彩的视觉效果&#xff0c;不禁会使人眼前一亮。接下来给大家介绍一款简易好用的视频编…

php 图片生成视频,图片转化为视频的方法 如何将照片制作成为视频

点击上方的下载地址&#xff0c;然后将软件进行安装。安装完毕后&#xff0c;打开软件在这个界面可以选择软件的比例大小和操作模式&#xff0c;我们选择“4:3”和“全功能模式”。 接着我们将要进行操作的图片导入到软件&#xff0c;点击“导入”后在“打开”界面选中所有的图…

ffmpeg使用(多个帧合成视频)

帧生成视频命令&#xff1a; ffmpeg -threads 2 -y -r 24 -i %05d.jpg output.mp4 视频生成帧命令&#xff08;按帧生成图片&#xff09;&#xff1a; ffmpeg -i checkpoints_dstt_car-turn_result.mp4 chaifen/%06d.png 1、下载ffmpeg安装包 https://github.com/BtbN/FFmpe…

matlab jpg合成gif,用MATLAB将照片合成视频或者GIF图片、以及Photoshop制作GIF图片

用MATLAB将照片合成视频或者GIF图片、以及Photoshop制作GIF图片 一、用MATLAB将照片合成视频(我使用的MATLAB是2015版本的) (1)、你需要需要合成视频的图片。 所有照片放在一个文件夹里面因为是使用Matlab的dir函数读取照片,所以读取时,你要先设置好文件名:图片名称按照“00…

FFmpeg初探——基于FFmpeg的图片合成视频

前言 商家在发布商品的时候&#xff0c;大部分情况下是没有视频的&#xff0c;这样往往会造成商品展示不全等问题&#xff0c;而视频制作又比较麻烦&#xff0c;为了解决此痛点&#xff0c;我们需要提供一键合成视频的功能。 之所以选择 FFmpeg&#xff0c;是因为我们期望后续能…

视频照片合成软件哪个好?快速把手机照片做成视频,简单操作,效果精美!

视频照片合成软件哪个好&#xff1f;怎么把照片合成视频&#xff1f;如何快速把手机照片做成视频&#xff1f; 这是我用数码大师把手机照片合成视频的效果截图&#xff1a; 第一步&#xff1a;快速导入多张照片&#xff0c;为照片配上文字 点击“添加相片”就能快速导入照片…

ffmpeg图片+音频合成视频

命令如下&#xff0c;个人纪录 ffmpeg -framerate 0.05 -f image2 -loop 1 -y -i d:/img/img%d.jpg -i d:/img/gyz.mp3 -s 1080*1920 -r 25 -t 100 d:/img/output.mp4 -framerate 速率&#xff0c;越小每张图片停留时间越长 -loop 循环一遍文件夹内的图片 -i 图片路径&#x…

用php把图片合成视频,图片音乐合成视频 多张图片合成视频|图片合成视频软件...

在网络上我们经常见到的电子相册其本质就是图片音乐合成视频&#xff0c;使用一些图片合成视频软件将多张图片合成视频&#xff0c;外加点炫酷的转场特效&#xff0c;so easy的就能完成了。o(*≧▽≦)ツ 想不想知道具体的操作过程&#xff1f;有兴趣的童鞋可以看看下文的~ 这是…

电脑图片合成视频用什么软件?3分钟快速教程,多张图片做成精美视频!

电脑图片合成视频怎么做&#xff1f;图片视频制作用什么软件好&#xff1f;现在大家的照片或图片很多&#xff0c;其实在电脑上把图片做成视频是非常方便的&#xff0c;还能整理好照片&#xff0c;节省空间&#xff0c;图片/照片视频看起来也更加美观。今天直接用数码大师教大家…