无向图G的广度优先搜索和深度优先搜索以及完整程序

2023-10-27

图的遍历算法有两种:广度优先搜索和深度优先搜索

一.广度优先搜索类似于层次遍历,需要借助辅助队列

空间复杂度为O(|V|);空间复杂度由辅助队列大小决定

时间复杂度为O(|V|+|E|)

为避免同一顶点被多次访问,设计visited[]来标记顶点

二.深度优先搜索类似于树的先序遍历,递归算法

空间复杂度:最好O(1),最坏O(|V|);

时间复杂度:O(|V|+|E|);

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

对于无向图进行BFS/DFS遍历:调用BFS/DFS函数的次数 = 连通分量数;对于连通图只需要调用1次BFS/DFS函数。

对于有向图进行BFS/DFS遍历:调用BFS/DFS函数的次数要具体问题具体分析;若起始顶点到其他顶点都有路径,只需要调用1次BFS/DFS函数;对于强连通图,从任一顶点出发都只需要调用1次BFS/DFS函数。

三.邻接矩阵存储图进行广度优先搜索和深度优先搜索

权值设置的都为1,可自行设置

圆圈内为顶点的值,上面为其序号;一该图为例进行邻接矩阵存储 

1.先创造邻接矩阵存储图

1.1图的结构体构造

typedef char VerTexType;//顶点的数据类型
typedef int EdgeType;//带权图中边上权值数据类型
typedef struct
{
  VerTexType Vex[MaxVertexNum];//顶点表
  EdgeType Edge[MaxVertexNum][MaxVertexNum];//邻接矩阵,边表
  int vexnum,arcnum;//图的当前顶点数和弧数
}MGraph;

1.2无向图邻接矩阵构造

//1.无向网的建立
void CreatMGraph(MGraph &G)
{
  printf("请输入图的顶点数和边数:");
  int m,n;
  scanf_s("%d %d",&m,&n);
  G.vexnum = m;
  G.arcnum = n;
  char val;
  for(int i = 0; i < G.vexnum; ++i)
  {
	  printf("第%d个顶点值为:",i);
	  scanf_s("%*c%c",&val);
	  G.Vex[i] = val;
  }
  for(int i = 0; i < G.vexnum; ++i)
  { 
	  for(int j = 0; j < G.vexnum; ++j)
	  {
		  G.Edge[i][j] = Max;
	  }
  }
  int i,j,w;
  for(int k = 0; k < G.arcnum; ++k)
  {
	printf("请输入顶点和权值\n");
	scanf_s("%d %d %d",&i,&j,&w);
    printf("(Vi,Vj)下表为(%d,%d)的权值为%d:\n",i,j,w);
	G.Edge[i][j] = w;
	G.Edge[j][i] = G.Edge[i][j];
  }

}

1.3FirstNeighbor函数构造

//2.求图G中顶点编号x的第一个邻接点
int FirstNeighbor(MGraph G, int x)
{

	for(int j = 0; j < G.vexnum; ++j)
	{
		if(G.Edge[x][j] != -1)
			return j;
	}
	return -1;
}

1.4NextNeighbor函数构造

//3.假设图G中顶点y是顶点x的一个邻近点,返回除y外顶点x的下一个邻接点的顶点号,若y是x的最后一个邻接点,则返回-1
int NextNeighbor(MGraph G, int x, int y)
{
  for(int j = y+1; j < G.vexnum; ++j)
  {
	  if(G.Edge[x][j] != -1)
		  return j;
  }
  return -1;
}

2.广度优先搜索的构造辅助队列

2.1辅助队列结构体

//定义队列的结构体
typedef struct LinkNode
{
  int data;//队列的数据域
  LinkNode *next;//指针域
}LinkNode;

typedef struct
{
  LinkNode *front;//队列对头指针
  LinkNode *rear;//队列队尾指针
}LinkQueue;

2.1初始化队列

//1.初始化
void InitQueue(LinkQueue &Q)
{
	Q.front = Q.rear = (LinkNode*)malloc(sizeof(LinkNode));
	Q.rear->next = NULL;
}

2.2入队函数

//2.入队
void EnQueue(LinkQueue &Q, int x)
{
  LinkNode *p = (LinkNode*)malloc(sizeof(LinkNode));
  if(p == NULL)
  {
    printf("动态内存分配失败!");
	exit(-1);
  }
  p->data = x;
  //通过尾插法入队
  p->next = NULL;
  Q.rear->next = p;
  Q.rear = p;
}

2.3出队函数

//3.出队
int DeQueue(LinkQueue &Q,int &x)
{
  if(IsEmpty(Q))
	  return -1;
  else
  {
	  LinkNode *p = Q.front->next;
	  x = p->data;
	  Q.front->next = p->next;
	  if(Q.rear == p)
		  Q.rear = Q.front;
	  free(p);
  }
  return x;
}

2.4判断队列为空

//4.判断空
bool IsEmpty(LinkQueue Q)
{
	if(Q.front == Q.rear)
	{
	  return true;
	}
	else
	{
	  return false;
	}
}

3.广度优先搜索

权值设置的都为1,可自行设置

以该例子进行邻接表存储 

3.1广度优先遍历图G

//广度优先搜索
//1.对图G进行广度优先遍历
void BFSTraverse(MGraph G)
{
	int *visited;
	visited = (int *)malloc(sizeof(int)*G.vexnum);
	for(int i = 0; i < G.vexnum; ++i)
	{
	  visited[i] = 0;
	}
	for(int i = 0; i < G.vexnum; ++i)
	{//从0号顶点遍历
	  if(!visited[i])//如果visited[i] == 0表示该点还未被访问
		  BFS(G,visited,i);//每个连通分量调用一次BFS函数
	}
	printf("\n");
}

3.2广度优先遍历

//2.广度优先遍历
void BFS(MGraph G,int *visited,int v)
{
	printf("%c ",G.Vex[v]);//打印输出初始顶点
	visited[v] = 1;//将打印过的顶点标记为true
	LinkQueue Q;
	InitQueue(Q);
	EnQueue(Q,v);//将顶点入队
	while(!IsEmpty(Q))//判断队列是否为空
	{
	  int u = DeQueue(Q,v);//不为空则出队
	  for(int w = FirstNeighbor(G,u); w >= 0; w = NextNeighbor(G,u,w))
	  {//检查序号v所有的邻接点
	    if(!visited[w])//如果序号为w的顶点还未被访问
		{
			printf("%c ",G.Vex[w]);
			visited[w] = 1;//将打印输出顶点的序号标记为1表示已经被访问
			EnQueue(Q,w);//将顶点入队
		}
	  }
	}

}

4.深度优先搜索

4.1深度优先遍历图G

//1.对图G进行深度优先遍历
void DFSTraverse(MGraph G)
{
	int *visited = (int *)malloc(sizeof(int)*G.vexnum);//创造标记组
	for(int i = 0; i < G.vexnum; ++i)
	{
	  visited[i] = 0;//等于0表示还未被访问,以免因为图中环的存在导致重复遍历
	}
	for(int i = 0; i < G.vexnum; ++i)//如果图中不止一个连通分量,可以将其全部遍历输出
	{
	  if(!visited[i])
		  DFS(G,visited,i);
	}
}

4.2深度优先遍历

//2.深度优先遍历
void DFS(MGraph G, int *visited, int v)
{
	printf("%c ",G.Vex[v]);//遍历输出顶点的值
	visited[v] = 1;//将该顶点的标记值改为1,表示该顶点已经被访问
	for(int w = FirstNeighbor(G,v); w >= 0; w = NextNeighbor(G,v,w))
	{
	  if(!visited[w])
		  DFS(G,visited,w);
	}

}

5.运行结果

四.无向图G邻接矩阵存储广度优先搜索和深度优先搜索

1.先创造邻接表 

1.1邻接表的结构体

#define MaxVertexNum 10//图中顶点数目的最大值
typedef char VertexType;
//邻接表的结构体
//定义边表结点
typedef struct ArcNode
{
  int adjvex;//该弧所指向的顶点的位置
  struct ArcNode *next;//指向下一条弧的指针
  int info;//网的边权值
}ArcNode;

//顶点表信息,用顺序结构存储顶点表的信息
typedef struct VNode
{
  VertexType data;//顶点信息
  ArcNode *first;//指向第一条依附该顶点的弧的指针
}VNode,AdjList[MaxVertexNum];

//邻接表
typedef struct
{
  AdjList vertices;//邻接表
  int vexnum,arcnum;//图的顶点数和弧数
}ALGraph;//ALGraph是以邻接表存储图的类型

 1.2创造邻接表

//创建邻接表
void CreatALGraph(ALGraph &G)
{
  printf("请输入图G的顶点数和边数:\n");
  scanf_s("%d %d",&(G.vexnum),&(G.arcnum));
  //输入结点
  char val;
  for(int i = 0; i < G.vexnum; ++i)
  {
    printf("请输入第%d个结点的值:\n",i);
	scanf_s("%*c%c",&val);
	G.vertices[i].data = val;
	G.vertices[i].first = NULL;//最开始令每个顶点的第一条依附顶点的弧的指针为空
  }
  //输入边
  int i,j,w;
  for(int k = 0; k < G.arcnum; ++k)
  {
	ArcNode *m = (ArcNode*)malloc(sizeof(ArcNode));
	printf("请输入顶点的序号和权值\n");
	scanf_s("%d %d %d",&i,&j,&w);
    printf("(Vi,Vj)下表为(%d,%d)的权值为%d:\n",i,j,w);
	m->adjvex = j;
	m->info = w;
	//用头插法创造边表
	m->next = G.vertices[i].first;
	G.vertices[i].first = m;
	//这个是无向图,而且令k<G.arcnum,因为一个弧对应两个顶点,两个顶点都是顶点表中的,所以要同时将两个顶点表的边表都弄好
	ArcNode *n = (ArcNode*)malloc(sizeof(ArcNode));
	n->adjvex = i;
	n->info = w;
	//用头插法创建边表
	n->next = G.vertices[j].first;
	G.vertices[j].first = n;
  }

}

1.3FirstNeighbor函数

//求图G中顶点x的第一个邻接点,若有则返回顶点号。若x没有邻接点或图中不存在x,则返回-1.
int FirstNeighbor(ALGraph G, int x)
{
	if(x >= G.vexnum)
	{
	  return -1;
	}
	else if(G.vertices[x].first == NULL)
	{	
	  return -1;
	}
	else
	{
		ArcNode *p = G.vertices[x].first;//指向图G的顶点x的邻接点的指针
		int i = p->adjvex;//邻接点的序号
		return i;
	}

}

1.4NextNeighbor函数

//假设图G中顶点y是顶点x的一个邻接点,返回除y外顶点x的下一个邻接点的顶点号,若y是x的最后一个邻接点,则返回-1
int NextNeighbor(ALGraph G,int x,int y)
{
	ArcNode *p = G.vertices[x].first;
	while(p->adjvex != y)
	{
		p = p->next;
	}
	if(p->next == NULL)
	{
		return -1;
	}
	else
	{
		p = p->next;
		int j = p->adjvex;
		return j;
	}
}

2.队列和上面一致,这里就不在展示代码

3.广度优先搜素和深度优先搜素和上面也是一致的,结尾有完整代码可以观看

4.运行结果:

 五.完整程序

1.以邻接矩阵存储进行广度优先和深度优先搜索

#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#define Max -1//这里以-1代表最大值
#define MaxVertexNum 15


typedef char VerTexType;//顶点的数据类型
typedef int EdgeType;//带权图中边上权值数据类型
typedef struct
{
  VerTexType Vex[MaxVertexNum];//顶点表
  EdgeType Edge[MaxVertexNum][MaxVertexNum];//邻接矩阵,边表
  int vexnum,arcnum;//图的当前顶点数和弧数
}MGraph;


//定义队列的结构体
typedef struct LinkNode
{
  int data;//队列的数据域
  LinkNode *next;//指针域
}LinkNode;

typedef struct
{
  LinkNode *front;//队列对头指针
  LinkNode *rear;//队列队尾指针
}LinkQueue;



//图G的函数说明
void CreatMGraph(MGraph &G);
int FirstNeighbor(MGraph G, int x);
int NextNeighbor(MGraph G, int x, int y);


//队列的函数说明
void InitQueue(LinkQueue &Q);
void EnQueue(LinkQueue &Q, int x);
int DeQueue(LinkQueue &Q,int &x);
bool IsEmpty(LinkQueue Q);


//广度优先遍历的函数说明
void BFSTraverse(MGraph G);
void BFS(MGraph G,int *visited,int v);

//深度优先遍历
void DFSTraverse(MGraph G);
void DFS(MGraph G, int *visited, int v);


int main(void)
{
  MGraph G;//定义变量图
  CreatMGraph(G);
  printf("广度优先遍历的结果:\n");
  BFSTraverse(G);
  printf("深度优先遍历的结果:\n");
  DFSTraverse(G);
  return 0;
}


//图G函数
//1.无向网的建立
void CreatMGraph(MGraph &G)
{
  printf("请输入图的顶点数和边数:");
  int m,n;
  scanf_s("%d %d",&m,&n);
  G.vexnum = m;
  G.arcnum = n;
  char val;
  for(int i = 0; i < G.vexnum; ++i)
  {
	  printf("第%d个顶点值为:",i);
	  scanf_s("%*c%c",&val);
	  G.Vex[i] = val;
  }
  for(int i = 0; i < G.vexnum; ++i)
  { 
	  for(int j = 0; j < G.vexnum; ++j)
	  {
		  G.Edge[i][j] = Max;
	  }
  }
  int i,j,w;
  for(int k = 0; k < G.arcnum; ++k)
  {
	printf("请输入顶点和权值\n");
	scanf_s("%d %d %d",&i,&j,&w);
    printf("(Vi,Vj)下表为(%d,%d)的权值为%d:\n",i,j,w);
	G.Edge[i][j] = w;
	G.Edge[j][i] = G.Edge[i][j];
  }

}

//2.求图G中顶点编号x的第一个邻接点
int FirstNeighbor(MGraph G, int x)
{

	for(int j = 0; j < G.vexnum; ++j)
	{
		if(G.Edge[x][j] != -1)
			return j;
	}
	return -1;
}

//3.假设图G中顶点y是顶点x的一个邻近点,返回除y外顶点x的下一个邻接点的顶点号,若y是x的最后一个邻接点,则返回-1
int NextNeighbor(MGraph G, int x, int y)
{
  for(int j = y+1; j < G.vexnum; ++j)
  {
	  if(G.Edge[x][j] != -1)
		  return j;
  }
  return -1;
}


//队列的函数

//1.初始化
void InitQueue(LinkQueue &Q)
{
	Q.front = Q.rear = (LinkNode*)malloc(sizeof(LinkNode));
	Q.rear->next = NULL;
}

//2.入队
void EnQueue(LinkQueue &Q, int x)
{
  LinkNode *p = (LinkNode*)malloc(sizeof(LinkNode));
  if(p == NULL)
  {
    printf("动态内存分配失败!");
	exit(-1);
  }
  p->data = x;
  //通过尾插法入队
  p->next = NULL;
  Q.rear->next = p;
  Q.rear = p;
}

//3.出队
int DeQueue(LinkQueue &Q,int &x)
{
  if(IsEmpty(Q))
	  return -1;
  else
  {
	  LinkNode *p = Q.front->next;
	  x = p->data;
	  Q.front->next = p->next;
	  if(Q.rear == p)
		  Q.rear = Q.front;
	  free(p);
  }
  return x;
}

//4.判断空
bool IsEmpty(LinkQueue Q)
{
	if(Q.front == Q.rear)
	{
	  return true;
	}
	else
	{
	  return false;
	}
}

//广度优先搜索
//1.对图G进行广度优先遍历
void BFSTraverse(MGraph G)
{
	int *visited;
	visited = (int *)malloc(sizeof(int)*G.vexnum);
	for(int i = 0; i < G.vexnum; ++i)
	{
	  visited[i] = 0;
	}
	for(int i = 0; i < G.vexnum; ++i)
	{//从0号顶点遍历
	  if(!visited[i])//如果visited[i] == 0表示该点还未被访问
		  BFS(G,visited,i);//每个连通分量调用一次BFS函数
	}
	printf("\n");
}

//2.广度优先遍历
void BFS(MGraph G,int *visited,int v)
{
	printf("%c ",G.Vex[v]);//打印输出初始顶点
	visited[v] = 1;//将打印过的顶点标记为true
	LinkQueue Q;
	InitQueue(Q);
	EnQueue(Q,v);//将顶点入队
	while(!IsEmpty(Q))//判断队列是否为空
	{
	  int u = DeQueue(Q,v);//不为空则出队
	  for(int w = FirstNeighbor(G,u); w >= 0; w = NextNeighbor(G,u,w))
	  {//检查序号v所有的邻接点
	    if(!visited[w])//如果序号为w的顶点还未被访问
		{
			printf("%c ",G.Vex[w]);
			visited[w] = 1;//将打印输出顶点的序号标记为1表示已经被访问
			EnQueue(Q,w);//将顶点入队
		}
	  }
	}

}


//深度优先遍历,类似于树的先序遍历

//1.对图G进行深度优先遍历
void DFSTraverse(MGraph G)
{
	int *visited = (int *)malloc(sizeof(int)*G.vexnum);//创造标记组
	for(int i = 0; i < G.vexnum; ++i)
	{
	  visited[i] = 0;//等于0表示还未被访问,以免因为图中环的存在导致重复遍历
	}
	for(int i = 0; i < G.vexnum; ++i)//如果图中不止一个连通分量,可以将其全部遍历输出
	{
	  if(!visited[i])
		  DFS(G,visited,i);
	}
}

//2.深度优先遍历
void DFS(MGraph G, int *visited, int v)
{
	printf("%c ",G.Vex[v]);//遍历输出顶点的值
	visited[v] = 1;//将该顶点的标记值改为1,表示该顶点已经被访问
	for(int w = FirstNeighbor(G,v); w >= 0; w = NextNeighbor(G,v,w))
	{
	  if(!visited[w])
		  DFS(G,visited,w);
	}

}

2.邻接表存储进行广度优先和深度优先搜索

#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>

#define MaxVertexNum 10//图中顶点数目的最大值
typedef char VertexType;
//邻接表的结构体
//定义边表结点
typedef struct ArcNode
{
  int adjvex;//该弧所指向的顶点的位置
  struct ArcNode *next;//指向下一条弧的指针
  int info;//网的边权值
}ArcNode;

//顶点表信息,用顺序结构存储顶点表的信息
typedef struct VNode
{
  VertexType data;//顶点信息
  ArcNode *first;//指向第一条依附该顶点的弧的指针
}VNode,AdjList[MaxVertexNum];

//邻接表
typedef struct
{
  AdjList vertices;//邻接表
  int vexnum,arcnum;//图的顶点数和弧数
}ALGraph;//ALGraph是以邻接表存储图的类型


//定义队列的结构体
typedef struct LinkNode
{
  int data;//队列的数据域
  LinkNode *next;//指针域
}LinkNode;

typedef struct
{
  LinkNode *front;//队列对头指针
  LinkNode *rear;//队列队尾指针
}LinkQueue;



//图的函数说明
void CreatALGraph(ALGraph &G);
int FirstNeighbor(ALGraph G, int x);
int NextNeighbor(ALGraph G,int x,int y);


//队列的函数说明
void InitQueue(LinkQueue &Q);
void EnQueue(LinkQueue &Q, int x);
int DeQueue(LinkQueue &Q,int &x);
bool IsEmpty(LinkQueue Q);


//广度优先遍历函数说明
void BFSTraverse(ALGraph G);
void BFS(ALGraph G, int *visited, int v);

//深度优先遍历函数说明
void DFSTraverse(ALGraph G);
void DFS(ALGraph G, int *visited, int v);


int main(void)
{
  ALGraph G;
  CreatALGraph(G);//以邻接表法存储图
  printf("广度优先遍历结果:\n");
  BFSTraverse(G);
  printf("深度优先遍历结果:\n");
  DFSTraverse(G);
  return 0;
}


//创建邻接表
void CreatALGraph(ALGraph &G)
{
  printf("请输入图G的顶点数和边数:\n");
  scanf_s("%d %d",&(G.vexnum),&(G.arcnum));
  //输入结点
  char val;
  for(int i = 0; i < G.vexnum; ++i)
  {
    printf("请输入第%d个结点的值:\n",i);
	scanf_s("%*c%c",&val);
	G.vertices[i].data = val;
	G.vertices[i].first = NULL;//最开始令每个顶点的第一条依附顶点的弧的指针为空
  }
  //输入边
  int i,j,w;
  for(int k = 0; k < G.arcnum; ++k)
  {
	ArcNode *m = (ArcNode*)malloc(sizeof(ArcNode));
	printf("请输入顶点的序号和权值\n");
	scanf_s("%d %d %d",&i,&j,&w);
    printf("(Vi,Vj)下表为(%d,%d)的权值为%d:\n",i,j,w);
	m->adjvex = j;
	m->info = w;
	//用头插法创造边表
	m->next = G.vertices[i].first;
	G.vertices[i].first = m;
	//这个是无向图,而且令k<G.arcnum,因为一个弧对应两个顶点,两个顶点都是顶点表中的,所以要同时将两个顶点表的边表都弄好
	ArcNode *n = (ArcNode*)malloc(sizeof(ArcNode));
	n->adjvex = i;
	n->info = w;
	//用头插法创建边表
	n->next = G.vertices[j].first;
	G.vertices[j].first = n;
  }

}

//求图G中顶点x的第一个邻接点,若有则返回顶点号。若x没有邻接点或图中不存在x,则返回-1.
int FirstNeighbor(ALGraph G, int x)
{
	if(x >= G.vexnum)
	{
	  return -1;
	}
	else if(G.vertices[x].first == NULL)
	{	
	  return -1;
	}
	else
	{
		ArcNode *p = G.vertices[x].first;//指向图G的顶点x的邻接点的指针
		int i = p->adjvex;//邻接点的序号
		return i;
	}

}

//假设图G中顶点y是顶点x的一个邻接点,返回除y外顶点x的下一个邻接点的顶点号,若y是x的最后一个邻接点,则返回-1
int NextNeighbor(ALGraph G,int x,int y)
{
	ArcNode *p = G.vertices[x].first;
	while(p->adjvex != y)
	{
		p = p->next;
	}
	if(p->next == NULL)
	{
		return -1;
	}
	else
	{
		p = p->next;
		int j = p->adjvex;
		return j;
	}
}


//队列的函数

//1.初始化
void InitQueue(LinkQueue &Q)
{
	Q.front = Q.rear = (LinkNode*)malloc(sizeof(LinkNode));
	Q.rear->next = NULL;
}

//2.入队
void EnQueue(LinkQueue &Q, int x)
{
  LinkNode *p = (LinkNode*)malloc(sizeof(LinkNode));
  if(p == NULL)
  {
    printf("动态内存分配失败!");
	exit(-1);
  }
  p->data = x;
  //通过尾插法入队
  p->next = NULL;
  Q.rear->next = p;
  Q.rear = p;
}

//3.出队
int DeQueue(LinkQueue &Q,int &x)
{
  if(IsEmpty(Q))
	  return -1;
  else
  {
	  LinkNode *p = Q.front->next;
	  x = p->data;
	  Q.front->next = p->next;
	  if(Q.rear == p)
		  Q.rear = Q.front;
	  free(p);
  }
  return x;
}

//4.判断空
bool IsEmpty(LinkQueue Q)
{
	if(Q.front == Q.rear)
	{
	  return true;
	}
	else
	{
	  return false;
	}
}


//广度优先遍历
//1.对图G进行广度优先遍历
void BFSTraverse(ALGraph G)
{
	int *visited = (int *)malloc(sizeof(int)*G.vexnum);
	for(int i = 0; i < G.vexnum; ++i)
	{
	  visited[i] = 0;//标记数组,等于0表示顶点还未被访问
	}
	for(int i = 0; i < G.vexnum; ++i)
	{
	  if(visited[i] == 0)
	     BFS(G,visited,i);
	}
	printf("\n");
}

//2.广度优先遍历
void BFS(ALGraph G, int *visited, int v)
{
	printf("%c ",G.vertices[v].data);
	visited[v] = 1;//改成1表示该顶点已经被访问
	LinkQueue Q;//定义队列变量
	InitQueue(Q);//初始化队列
	EnQueue(Q,v);//入队
	while(!IsEmpty(Q))
	{
	  DeQueue(Q,v);//出队
	  for(int w = FirstNeighbor(G,v); w >= 0; w = NextNeighbor(G,v,w))
	  {
	    if(visited[w] == 0)
		{
			printf("%c ",G.vertices[w].data);//将第一个邻接点打印输出
			visited[w] = 1;//将该顶点标记为已经访问
			EnQueue(Q,w);//将顶点入队
		}
	  }
	}
}


//1.对图G进行深度优先遍历
void DFSTraverse(ALGraph G)
{
  	int *visited = (int *)malloc(sizeof(int)*G.vexnum);
	for(int i = 0; i < G.vexnum; ++i)
	{
	  visited[i] = 0;//标记数组,等于0表示顶点还未被访问
	}
	for(int i = 0; i < G.vexnum; ++i)
	{
      if(visited[i] == 0)
	     DFS(G,visited,i);
	}
	printf("\n");
}

//2.深度优先遍历
void DFS(ALGraph G, int *visited, int v)
{
	printf("%c ",G.vertices[v].data);
	visited[v] = 1;
	for(int w = FirstNeighbor(G,v); w >= 0; w = NextNeighbor(G,v,w))
	{
		if(visited[w] == 0)
		{
			visited[w] = 1;
			DFS(G,visited,w);//进行递归
		}
	}
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

无向图G的广度优先搜索和深度优先搜索以及完整程序 的相关文章

随机推荐

  • 基于STM32的智能小车--电机驱动设计

    基于STM32的智能小车 第一章 基于STM32的智能小车方案设计 基于STM32的智能小车 电机驱动设计 基于STM32的智能小车 前言 一 电机是什么 二 常见电机分类 1 有刷电机 2 无刷电机 二 有刷电机和无刷电机在调速上的差异
  • go 进阶 九. 定时器

    目录 一 Timer 内部包含的方法解释 1 创建定时器 2 停止定时器 3 重置定时器 4 After 匿名定时器 5 AfterFunc 延迟执行 使用场景举例 原理 1 底层结构 2 创建Timer 3 停止Timer 4 重置Tim
  • Vc - Qt - 仿微信聊天工具

    从小白开始 成神成魔之路记录 评论区 记录生活 一年成神 评论区自己可用其他人不可用 2021 11 13 8 49 仿照微信项目 服务器端 查找某个玩家的结果记录 2021 11 14 21 37 仿照微信服务器端 实现根据usernam
  • DVWA-----SQL Injection(SQL手工注入)

    目录 一 SQL注入 1 SQL注入原理 2 SQL注入分类 3 SQL注入思路 4 SQL注入绕过方法 二 SQL注入漏洞的分析 1 定义 2 原因 3 危害 三 Web 程序三层架构 四 SQL Injection 1 LOW 2 Me
  • odoo13 订单模板设置_ERP输出嵌入公章的采购订单电子档,其实真的不难

    企业里 采购订单 的发送是最频繁的工作 在过去还得打印出来 领导签完字 盖个章才可以传真出去 到如今 随着电子档的应用与通讯工具的普及 都是直接从ERP中输出PDF 再通过微信或QQ发给供应商 那下面我们介绍一下云上软件是怎么实现这个效果的
  • 商业思维--反向理论的合理性

    创业 是一种破坏 如果这种破坏不足够像美国的卡梅隆导演的电影一样 格局要大 步骤要细 反向理论是很多初期萌生创业想法的角斗士 那时候 的我们总是觉得思维远超爱因斯坦 然后寻找自我认知里的实现步骤 往往得到是 马爸说得 今天很多想法 睡一觉就
  • 【LLM】微调LLM:LoRA 还是全参数?Llama 2 的深入分析

    大家好 我是Sonhhxg 柒 希望你看完之后 能对你有所帮助 不足请指正 共同学习交流 个人主页 Sonhhxg 柒的博客 CSDN博客 欢迎各位 点赞 收藏 留言 系列专栏 机器学习 ML 自然语言处理 NLP 深度学习 DL fore
  • CAS 未认证授权服务 不允许使用CAS来认证您访问的目标应用

    资源环境 CAS服务端 CAS 5 3 2 服务端 CAS客户端 Spring Boot CAS 客户端 访问过程 1 CAS 客户端访问本地项目指定端口 http localhost 9100 cas index 2 CAS 客户端调整至
  • tictoc例子理解 16-18

    tictoc16 18 tictoc 16 全局信号signal tictoc 17 在仿真界面幕布上显示总条数信息 tictoc 18 tictoc 16 全局信号signal 前一步的主要问题是 如果我们想要更改所收集的统计信息 就必须
  • html msn 消息,msn.html

    canvas 心 html body height 100 padding 0 margin 0 background 000 canvas position absolute width 100 height 100 Settings v
  • 51中断系统与vhdl状态机

    51中断系统与vhdl状态机 51单片机中断系统 1 为什么要引入中断 List item 51单片机中断系统 1 为什么要引入中断 中断是为使单片机具有对外部或内部随机发生的事件实时的处理而设置的 中断功能的存在 很大程度上提高了单片机处
  • vue中使用MINIO将文件上传到指定的bucket库中(vue2和vue3)

    步骤 MINIO官网 https docs min io docs javascript client quickstart guide html 下载minio npm install save minio 将minio集成到js中 在集
  • 分享一个基于Python和Django的产品销售收入数据分析系统源码

    作者 计算机源码社 个人简介 本人七年开发经验 擅长Java Python PHP NET 微信小程序 爬虫 大数据等 大家有这一块的问题可以一起交流 学习资料 程序开发 技术解答 文档报告 JavaWeb项目 微信小程序项目 Python
  • VScode远程连接服务器-过程试图写入的管道不存在-could not establist connection to【已解决】

    问题描述 使用服务器的过程中突然与服务器断连 报错如下 could not establist connection to 20 23 39 487 gt ssh connect to host 10 201 0 131 port 22 C
  • python卡方检验关键词,特征选择——卡方检验(使用Python sklearn进行实现)

    在看这篇文章之前 如果对卡方检验不熟悉 可以先参考 卡方检验 Python有包可以直接实现特征选择 也就是看自变量对因变量的相关性 今天我们先开看一下如何用卡方检验实现特征选择 1 首先import包和实验数据 from sklearn f
  • IntelliJ IDEA中生成jar包

    IntelliJ IDEA中的java项目 比如 myproject 可以生成jar包 本文以IntelliJ IDEA 2018 2 5版本为例进行介绍 方法如下 1 依次选择菜单 File gt Project Structure 打开
  • 下载安装和汉化Eclipse(详细)

    文章目录 前言 Eclipse的下载安装 总结 前言 本文详细叙述了 Eclipse的下载安装 在使用Eclipse之前需要准备好Java环境 可参考这里 JDK的下载安装和配置 提示 以下是本篇文章正文内容 下面案例可供参考 Eclips
  • mysql报错代码10051_socket error 10061/11004/10053/10051等错误总结

    Socket是应用层与TCP IP协议族通信的中间软件抽象层 它是一组接口 在设计模式中 Socket其实就是一个门面模式 它把复杂的TCP IP协议族隐藏在Socket接口后面 对用户来说 一组简单的接口就是全部 让Socket去组织数据
  • 正点原子IM6XULL阿尔法USB摄像头的远程调用(一)硬件连接

    正点原子IMX6ULL阿尔法USB摄像头的远程调用 一 硬件连接 话不多说 直接上货 1 用电源线连接电源 如图所示 2 利用USB接串口线将板子和电脑相连 电脑用U口 板子用USB UART口 如图所示 3 按开机键开机 如图所示 4 从
  • 无向图G的广度优先搜索和深度优先搜索以及完整程序

    图的遍历算法有两种 广度优先搜索和深度优先搜索 一 广度优先搜索类似于层次遍历 需要借助辅助队列 空间复杂度为O V 空间复杂度由辅助队列大小决定 时间复杂度为O V E 为避免同一顶点被多次访问 设计visited 来标记顶点 二 深度优