数据结构——图的深度(DFS)和广度优先所搜遍历(BFS)

数据结构——图的深度(DFS)和广度优先所搜遍历(BFS)

使用邻接矩阵和邻接表结构存储图。输入或存储一个无向图,根据一个初始顶点,输出图的深度和广度优先搜索遍历路径。
代码片.

//-------邻接矩阵(数组)存储表示-------
void DFSTraverse_Matrix(MatrixGraph G, int v)
{//深度优先搜索遍历-递归
	printf("%c", G.vexs[v]);
	visited[v] = true;
	for (int i = 0; i < G.vexnum; i++)
	{
		if (G.arcs[v][i].adj != 0 && !visited[i])
		{//adj!=0说明v i之间有连接,并且若第i点没被访问过
		 //继续进行递归
			printf("-->");
			DFSTraverse_Matrix(G, i);
		}

	}
}
void DFS_Matrix(MatrixGraph G, char V0)
{//深度优先搜索遍历函数入口
	int v = LocateMatrixVex(G, V0);
	for (int i = 0; i < MAX_VERTEX_NUM; i++)
	{//visited数组初始化,初始状态都未访问;
		visited[i] = false;
	}
	DFSTraverse_Matrix(G, v);
	printf("\n");
	//以下循环为查找为确保与V0不连通的点也能被访问
	for (int i = 0; i < G.vexnum; i++)
	{
		if (visited[i] == false)
		{
			DFSTraverse_Matrix(G, i);
			printf("\n");
		}
	}
	printf("\n");
}
/*
邻接矩阵的广度优先搜索遍历
*/
void BFS_Matrix(MatrixGraph & G, char V0)
{
	int v = LocateMatrixVex(G, V0);
	for (int i = 0; i < G.vexnum; i++) //visited[MAX_VERTEX_NUM]初始化
	{
		visited[i] = false;
	}
	for (int i = 0; i < G.vexnum; i++)
	{
		char u, w, V0;
		if (i == 0)
		{
			V0 = G.vexs[v];
			v = LocateMatrixVex(G, V0);
		}
		else if (visited[i])
		{
			continue;
		}
		else
		{
			V0 = G.vexs[i];
			v = LocateMatrixVex(G, V0);
		}
		queue<char> q;
		printf("%c", V0);
		visited[v] = true;
		q.push(V0);
		while (!q.empty())
		{
			u = q.front();
			v = LocateMatrixVex(G, u);
			q.pop();
			for (int i = 0; i < G.vexnum; i++)
			{
				w = G.vexs[i];
				if (G.arcs[v][i].adj != 0 && !visited[i])
				{
					printf("-->%c", w);
					q.push(w);
					visited[i] = true;
				}
			}
		}
		printf("\n");
	}
	printf("\n");
}

代码片

//-------邻接表存储表示-------
//(算法与邻接矩阵存储一致)
void DFSTraverse_List(ListGraph G, int v)
{//深度优先搜索遍历-递归
   int w;
   printf("%c", G.vertices[v].data);
   visited[v] = true;
   ArcNode * p = new ArcNode;
   p = G.vertices[v].firstarc;
   while (p)
   {
   	w = p->adjvex;
   	if (!visited[w])
   	{
   		printf("-->");
   		DFSTraverse_List(G, w);
   	}
   	p = p->nextarc;
   }
}
void DFS_List(ListGraph	G, char V0)
{//邻接表深度优先搜索遍历函数入口
   int v = LocateListVex(G, V0);
   for (int i = 0; i < G.vexnum; i++)
   {
   	if (i == 0)
   	{
   		DFSTraverse_List(G, v);
   		printf("\n");
   	}
   	else if (i != 0 && !visited[i])
   	{
   		DFSTraverse_List(G, i);
   		printf("\n");
   	}
   }
}
//邻接表的广度优先搜索遍历
int BFS_List(ListGraph G, char V0)
{
   int v = LocateListVex(G, V0);
   for (int i = 0; i < MAX_VERTEX_NUM; i++)
   {
   	visited[i] = false;
   }
   for (int i = 0; i < G.vexnum; i++)
   {
   	if (i != 0 && !visited[i])
   		v = i;
   	else if (visited[i])
   	{
   		continue;
   	}
   	int u, w;
   	char V0 = G.vertices[v].data;
   	queue<char> q;
   	printf("%c", V0);//打印顶点v0
   	v = LocateListVex(G, V0); //找到v0对应的下标
   	visited[v] = true;//顶点v0已被访问
   	q.push(V0);//将顶点v0入队
   	ArcNode * p = new ArcNode;
   	while (!q.empty())
   	{
   		u = q.front();//将顶点元素u出队,开始访问u的所有邻接点
   		v = LocateListVex(G, u);//得到顶点u的对应下标
   		q.pop();//将顶点u出队
   		for (p = G.vertices[v].firstarc; p; p = p->nextarc)//遍历顶点u的邻接点
   		{
   			w = p->adjvex;
   			if (!visited[w])//顶点p未被访问
   			{
   				printf("-->%c", G.vertices[w].data); //打印顶点p
   				visited[w] = 1;	//顶点p已被访问
   				q.push(G.vertices[w].data);//将顶点p入队
   			}
   		}
   	}
   	printf("\n");
   }
   return 0;
}

完整代码

代码片

文件Graph.h
#pragma once
#ifndef _GRAPH_H_
#define _GRAPH_H_
#define MAX_VERTEX_NUM 20	//最大顶点个数
#define MAX_ARC_NUM 190		//最大边数
#define MAX_NUM (~(0x1<<31))//最大值
#define ERROR -1
#define OK 0
#include <stdio.h>
#include <queue>
using namespace std;
//bool visited[MAX_VERTEX_NUM];
typedef int VRType;
typedef int InfoType;
typedef char VertexType;
typedef enum { DG, DN, UDG, UDN } GraphKind;
using namespace std;

typedef struct ArcCell
{//弧的定义
   VRType adj;	//对无权图,用1和0表示相邻否;对带权图,则为全职类型
   InfoType* info; //该弧相关信息的指针
}ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedef struct
{
   VertexType vexs[MAX_VERTEX_NUM]; //顶点向量
   AdjMatrix arcs; //邻接矩阵
   int vexnum, arcnum; //顶点数和弧数
   GraphKind kind; //图的类型
}MatrixGraph;

typedef struct ArcNode
{//邻接表顶点
   int adjvex;
   ArcNode * nextarc;
   InfoType * info;
}ArcNode;
typedef struct VexNode
{//邻接表顶点列表
   VertexType data;
   ArcNode *firstarc;
}VexNode, AdjList[MAX_VERTEX_NUM];
typedef struct
{//图的邻接表形式
   int vexnum, arcnum;
   GraphKind kind;
   AdjList vertices;
}ListGraph;

typedef struct
{//Prim——记录数组
   VertexType adjvex;
   VRType lowcost;
}CLOSEDGE[MAX_VERTEX_NUM];

typedef struct
{//带权图边集
   VertexType v1, v2;
   VRType info;
}Edge, Edges[MAX_ARC_NUM];
/*
邻接矩阵相关函数
*/
int LocateMatrixVex(MatrixGraph G, VertexType V);//定位点V在G中的位置
int CreatMatrixUDG(MatrixGraph & G);//创建无向图
int CreatMatrixUDN(MatrixGraph & G);//创建无向网
void DFSTraverse_Matrix(MatrixGraph G, int v);//深度优先遍历(递归)
void DFS_Matrix(MatrixGraph G, char V0);//深度优先遍历入口
void BFS_Matrix(MatrixGraph & G, char V0);//广度优先遍历
//MatrixGraph CreatTestMatrixUDN(MatrixGraph & G); //供测试使用的无向网(已删除)
//MatrixGraph CreatTestMatrixUDG(MatrixGraph & G); //供测试使用的无向图
/*
邻接表相关函数
*/
int LocateListVex(ListGraph G, VertexType V); //定位点V在G中位置
int CreatListUDG(ListGraph & G); //创建无向图
int CreatListUDN(ListGraph & G, Edges & edge); //创建无向网
//int CreatTestListUDG(ListGraph & G); //创建供测试的无向图(已删除)
void DFSTraverse_List(ListGraph G, int v); //深度优先遍历(递归)
void DFS_List(ListGraph	G, char V0); //深度优先遍历函数入口
int BFS_List(ListGraph G, char V0); //广度优先遍历

#endif // !_GRAPH_H_

代码片

#include "stdafx.h"
#include "Graph.h"

bool visited[MAX_VERTEX_NUM] = { false };

//定位点在图中的位置
int LocateMatrixVex(MatrixGraph G, VertexType V)
{
   for (int i = 0; i < G.vexnum; i++)
   {
   	if (V == G.vexs[i])
   		return i;
   }
   return ERROR;
}

//创建无向图
int CreatMatrixUDG(MatrixGraph & G)
{

   char c;
   VertexType V1, V2;
   G.kind = UDN;
   printf("请输入无向图的顶点数和弧数:(例: 2 3)\n");
   scanf("%d %d", &G.vexnum, &G.arcnum);
   while ((c = getchar()) != '\n'&&c != EOF);
   for (int i = 0; i < G.vexnum; i++)
   {
   	printf("请输入第%d个顶点的符号:\n", i + 1);
   	scanf("%c", &G.vexs[i]);
   	while ((c = getchar()) != '\n'&&c != EOF); //清楚输入缓存
   }
   //矩阵的初始化
   for (int i = 0; i < G.vexnum; i++)
   {
   	for (int j = 0; j < G.vexnum; j++)
   	{
   		G.arcs[i][j].adj = 0;
   		G.arcs[i][j].info = NULL;
   	}
   }
   printf("请输入有连接的点:(例如:A B)\n");
   for (int i = 0, j, k; i < G.arcnum; i++)
   {
   	printf("第%d对连接点:", i + 1);
   	scanf("%c %c", &V1, &V2);
   	while ((c = getchar()) != '\n'&&c != EOF);
   	j = LocateMatrixVex(G, V1); //获取矩阵下标
   	k = LocateMatrixVex(G, V2);
   	G.arcs[j][k].adj = 1; //修改矩阵值
   	G.arcs[k][j].adj = G.arcs[j][k].adj; //无向图矩阵为对称矩阵
   }
   return OK;
}

//创建无向有权图
int CreatMatrixUDN(MatrixGraph & G)
{

   char c;
   VertexType V1, V2;
   G.kind = UDN;
   printf("请输入无向图的顶点数和弧数:(例: 2 3)\n");
   scanf("%d %d", &G.vexnum, &G.arcnum);
   while ((c = getchar()) != '\n'&&c != EOF);
   for (int i = 0; i < G.vexnum; i++)
   {
   	printf("请输入第%d个顶点的符号:\n", i + 1);
   	scanf("%c", &G.vexs[i]);
   	while ((c = getchar()) != '\n'&&c != EOF); //清楚输入缓存
   }
   //矩阵的初始化
   for (int i = 0; i < G.vexnum; i++)
   {
   	for (int j = 0; j < G.vexnum; j++)
   	{
   		G.arcs[i][j].adj = 0;
   		G.arcs[i][j].info = NULL;
   	}
   }
   printf("请输入有连接的点以及两点之间的权值:(例如:A B 5)\n");
   for (int i = 0, j, k; i < G.arcnum; i++)
   {
   	int adj = 0;
   	printf("第%d对连接点:", i + 1);
   	scanf("%c %c %d", &V1, &V2, &adj);
   	while ((c = getchar()) != '\n'&&c != EOF);
   	j = LocateMatrixVex(G, V1); //获取矩阵下标
   	k = LocateMatrixVex(G, V2);
   	G.arcs[j][k].adj = adj; //修改矩阵值
   	G.arcs[k][j].adj = G.arcs[j][k].adj; //无向图矩阵为对称矩阵
   }
   return OK;
}

//深度优先搜索遍历 
//对结点是否被访问进行记录,初始状态都未访问;
void DFSTraverse_Matrix(MatrixGraph G, int v)
{
   printf("%c", G.vexs[v]);
   visited[v] = true;
   for (int i = 0; i < G.vexnum; i++)
   {
   	if (G.arcs[v][i].adj != 0 && visited[i] == false)
   	{
   		printf("-->");
   		DFSTraverse_Matrix(G, i);

   	}

   }
}
void DFS_Matrix(MatrixGraph G, char V0)
{
   int v = LocateMatrixVex(G, V0);
   for (int i = 0; i < MAX_VERTEX_NUM; i++)
   {//visited数组初始化,初始状态都未访问;
   	visited[i] = false;
   }
   DFSTraverse_Matrix(G, v);
   printf("\n");
   for (int i = 0; i < G.vexnum; i++)
   {
   	if (visited[i] == false)
   	{
   		DFSTraverse_Matrix(G, i);
   		printf("\n");
   	}
   }
   printf("\n");
}

/*
邻接矩阵的广度优先搜索遍历
*/

void BFS_Matrix(MatrixGraph & G, char V0)
{
   int v = LocateMatrixVex(G, V0);
   for (int i = 0; i < G.vexnum; i++) //visited[MAX_VERTEX_NUM]初始化
   {
   	visited[i] = false;
   }
   for (int i = 0; i < G.vexnum; i++)
   {
   	char u, w, V0;
   	if (i == 0)
   	{
   		V0 = G.vexs[v];
   		v = LocateMatrixVex(G, V0);
   	}
   	else if (visited[i])
   	{
   		continue;
   	}
   	else
   	{
   		V0 = G.vexs[i];
   		v = LocateMatrixVex(G, V0);
   	}
   	queue<char> q;
   	printf("%c", V0);
   	visited[v] = true;
   	q.push(V0);
   	while (!q.empty())
   	{
   		u = q.front();
   		v = LocateMatrixVex(G, u);
   		q.pop();
   		for (int i = 0; i < G.vexnum; i++)
   		{
   			w = G.vexs[i];
   			if (G.arcs[v][i].adj != 0 && !visited[i])
   			{
   				printf("-->%c", w);
   				q.push(w);
   				visited[i] = true;
   			}
   		}
   	}
   	printf("\n");
   }
   printf("\n");
}
//查找V点图中的位置
int LocateListVex(ListGraph G, VertexType V)
{
   for (int i = 0; i < G.vexnum; i++)
   {
   	if (G.vertices[i].data == V)
   		return i;
   }
   return ERROR;
}
//创建邻接表
int CreatListUDG(ListGraph & G)
{
   int c, j, k;
   VertexType V1, V2;
   G.kind = UDG;
   printf("请输入图的顶点数和边数:(例如:3 2)\n");
   scanf("%d %d", &G.vexnum, &G.arcnum);
   while ((c = getchar()) != '\n'&&c != EOF);
   for (int i = 0; i < G.vexnum; i++)
   {
   	printf("请输入第%d个顶点\n", i + 1);
   	scanf("%c", &G.vertices[i].data);
   	while ((c = getchar()) != '\n'&&c != EOF);
   	G.vertices[i].firstarc = NULL;
   }
   for (int i = 0; i < G.arcnum; i++)
   {
   	printf("请输入第%d条弧的两端顶点:(例如:A B)\n", i + 1);
   	scanf("%c %c", &V1, &V2);
   	while ((c = getchar()) != '\n'&&c != EOF);
   	k = LocateListVex(G, V1); //找到顶点i的下标
   	j = LocateListVex(G, V2); //找到顶点j的下标
   	ArcNode *p1 = new ArcNode; //创建一个边结点*p1
   	p1->adjvex = j;	//其邻接点域为j
   	p1->nextarc = G.vertices[k].firstarc;
   	G.vertices[k].firstarc = p1; // 将新结点*p插入到顶点v1的边表头部
   	ArcNode *p2 = new ArcNode;//另一对
   	p2->adjvex = k;
   	p2->nextarc = G.vertices[j].firstarc;
   	G.vertices[j].firstarc = p2;
   }
   return 0;
}
int CreatListUDN(ListGraph & G, Edges & edge)
{
   int c, j, k;
   VRType n;
   VertexType V1, V2;
   G.kind = UDN;
   printf("请输入图的顶点数和边数:(例如:3 2)\n");
   scanf("%d %d", &G.vexnum, &G.arcnum);
   while ((c = getchar()) != '\n'&&c != EOF);
   for (int i = 0; i < G.vexnum; i++)
   {
   	printf("请输入第%d个顶点\n", i + 1);
   	scanf("%c", &G.vertices[i].data);
   	while ((c = getchar()) != '\n'&&c != EOF);
   	G.vertices[i].firstarc = NULL;
   }
   for (int i = 0; i < G.arcnum; i++)
   {
   	printf("请输入第%d条边的两端顶点以及边的权值:(例如:A B 5)\n", i + 1);
   	scanf("%c %c %d", &V1, &V2, &n);
   	while ((c = getchar()) != '\n'&&c != EOF);
   	edge[i]= { V1, V2, n };
   	k = LocateListVex(G, V1); //找到顶点i的下标
   	j = LocateListVex(G, V2); //找到顶点j的下标
   	ArcNode *p1 = new ArcNode; //创建一个边结点*p1
   	p1->adjvex = j;	//其邻接点域为j
   	p1->nextarc = G.vertices[k].firstarc;
   	p1->info = &n; //权值
   	G.vertices[k].firstarc = p1; // 将新结点*p插入到顶点v1的边表头部
   	ArcNode *p2 = new ArcNode;//另一对
   	p2->adjvex = k;
   	p2->nextarc = G.vertices[j].firstarc;
   	p2->info = &n;
   	G.vertices[j].firstarc = p2;
   }
   return OK;
}

//邻接表的深度优先搜索
void DFSTraverse_List(ListGraph G, int v)
{
   int w;
   printf("%c", G.vertices[v].data);
   visited[v] = true;
   ArcNode * p = new ArcNode;
   p = G.vertices[v].firstarc;
   while (p)
   {
   	w = p->adjvex;
   	if (!visited[w])
   	{
   		printf("-->");
   		DFSTraverse_List(G, w);
   	}
   	p = p->nextarc;
   }
}
void DFS_List(ListGraph	G, char V0)
{
   int v = LocateListVex(G, V0);
   for (int i = 0; i < G.vexnum; i++)
   {
   	if (i == 0)
   	{
   		DFSTraverse_List(G, v);
   		printf("\n");
   	}
   	else if (i != 0 && !visited[i])
   	{
   		DFSTraverse_List(G, i);
   		printf("\n");
   	}
   }
}
//邻接表的广度优先搜索遍历

int BFS_List(ListGraph G, char V0)
{
   int v = LocateListVex(G, V0);
   for (int i = 0; i < MAX_VERTEX_NUM; i++)
   {
   	visited[i] = false;
   }
   for (int i = 0; i < G.vexnum; i++)
   {
   	if (i != 0 && !visited[i])
   		v = i;
   	else if (visited[i])
   	{
   		continue;
   	}
   	int u, w;
   	char V0 = G.vertices[v].data;
   	queue<char> q;
   	printf("%c", V0);//打印顶点v0
   	v = LocateListVex(G, V0); //找到v0对应的下标
   	visited[v] = true;//顶点v0已被访问
   	q.push(V0);//将顶点v0入队
   	ArcNode * p = new ArcNode;
   	while (!q.empty())
   	{
   		u = q.front();//将顶点元素u出队,开始访问u的所有邻接点
   		v = LocateListVex(G, u);//得到顶点u的对应下标
   		q.pop();//将顶点u出队
   		for (p = G.vertices[v].firstarc; p; p = p->nextarc)//遍历顶点u的邻接点
   		{
   			w = p->adjvex;
   			if (!visited[w])//顶点p未被访问
   			{
   				printf("-->%c", G.vertices[w].data); //打印顶点p
   				visited[w] = 1;	//顶点p已被访问
   				q.push(G.vertices[w].data);//将顶点p入队
   			}
   		}
   	}
   	printf("\n");
   }
   return 0;
}

代码片

文件:main.cpp
// main.cpp: 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <stdlib.h>
#include "Graph.h"
#include "MinCostSpanTree.h"
int main()
{
   int switch_on, c;
   printf("********输出图的深度搜索遍历和广度搜索遍历********\n");
   printf("1、使用邻接矩阵(数组)存储图;\n");
   printf("2、使用邻接表存储图;\n");
   printf("3、图的最小生成树——Prim算法;\n");
   printf("4、图的最小生成树——Kruscal算法;\n");
   printf("请输入选项:");
   scanf("%d", &switch_on);
   while ((c = getchar()) != '\n'&&c != EOF);
   switch (switch_on)
   {
   case 1:
   {
   	MatrixGraph G;
   	char i;
   	CreatMatrixUDG(G);
   	//G = CreatTestUDNraph(G);
   	printf("请输入初始点:\n");
   	scanf("%c", &i);
   	while ((c = getchar()) != '\n'&&c != EOF);
   	printf("深度优先搜素遍历结果:\n");
   	DFS_Matrix(G, i);
   	printf("广度优先搜索遍历结果:\n");
   	BFS_Matrix(G, i);
   	break;
   }
   case 2:
   {
   	char i;
   	ListGraph G;
   	CreatListUDG(G);
   	printf("请输入初始点:\n");
   	scanf("%c", &i);
   	while ((c = getchar()) != '\n'&&c != EOF);
   	printf("深度优先搜索遍历结果:\n");
   	DFS_List(G, i);
   	printf("\n广度优先搜索遍历结果:\n");
   	BFS_List(G, i);
   	break;
   }
   default:
   	break;
   }
   system("pause");
   return 0;
}
//测试数据如下图输入

测试例图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值