图的实现和图的深度遍历 Graph's DFS

本文介绍图的两种存储方式:邻接矩阵法和邻接表法,并详细阐述了这两种存储方式下的深度优先搜索(DFS)算法实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

图的存储有2种方式:

1、数组形式存储的邻接矩阵法

2、链表形式存储的邻接表法。

图的遍历方法有2种方式:

1、深度优先遍历

2、广度优先遍历


一、图的存储

数组形式存储的邻接矩阵法:

这里我们申请一块矩阵大小的连续空间,然后用一个数组指针来操作二维数组,如edge[i][j]。

int (*edge)[VERTEXNUM] = (int (*)[VERTEXNUM])malloc(sizeof(int)*VERTEXNUM*VERTEXNUM);


链表形式存储的邻接表法:

1. 某个结点所能到达的结点将会组成一个单链表(称作邻接表),那么一个拥有n个结点的图将会有n个邻接表。这样一个A点所拥有的邻接表中所有的结点都意味着“从A点出发到某个点有一条边”。

我们用下面的结构来表示邻接表中的一个结点:

typedef struct edge{
int vertex;  //该边所到达的结点编号
struct edge *next;  //邻接的下一条边
}st_edge;//这里没有存储这个表示从那儿出发的,因为每个邻接表所有边的出发结点都一致。

2. 各个单链表的首结点地址将会存在一个连续数组中,便于访问。

st_edge** edge = (st_edge**)malloc(sizeof(st_edge*)*VERTEXNUM);

查找某个结点所拥有的邻接表,需要在edge基础上向后移动指针。*(edge+i)是图的i号点的邻接表的首结点地址。



二、图的遍历

设置一个全局数组来保存遍历情况

int *vertexStatusArr = (int*)malloc(sizeof(int)*VERTEXNUM);


邻接矩阵的DFS深度遍历:

void dfs(int (*edge)[VERTEXNUM], int* vertexStatusArr)
{
	int i;
	printf("DFS: \n");
	for(i=0;i<VERTEXNUM;i++)
		dfscore(edge, i, vertexStatusArr);
	printf("\n");
}

void dfscore(int (*edge)[VERTEXNUM], int i, int* vertexStatusArr)
{
	if(vertexStatusArr[i] == 1)
		return;
	printf("%d ", i);
	vertexStatusArr[i] = 1;

	for(int j=0;j<VERTEXNUM;j++)
		if(edge[i][j] == 1)
			dfscore(edge, j , vertexStatusArr);
}

邻接表的DFS深度遍历:

void dfs(st_edge** edge, int* vertexStatusArr)
{
	printf("DFS: ");
	int i;
	for(i=0;i<VERTEXNUM;i++)
		dfscore(edge, i, vertexStatusArr);
	printf("\n");
}

void dfscore(st_edge** edge, int i, int* vertexStatusArr)
{
	if(vertexStatusArr[i] == 1)
		return;
	printf("%d ", i);
	vertexStatusArr[i] = 1;

	st_edge* p = *(edge+i);
	while(p != NULL)
	{
		dfscore(edge, p->vertex, vertexStatusArr);
		p = p->next;
	}
}






完整代码:

//邻接矩阵的深度优先遍历
#include <stdio.h>
#include <malloc.h>
#define VERTEXNUM 5

void createGragh(int (*edge)[VERTEXNUM], int start, int end);
void display(int (*edge)[VERTEXNUM]);
void dfs(int (*edge)[VERTEXNUM], int* vertexStatusArr);
void dfscore(int (*edge)[VERTEXNUM], int i, int* vertexStatusArr);

void dfs(int (*edge)[VERTEXNUM], int* vertexStatusArr)
{
	int i;
	printf("DFS: \n");
	for(i=0;i<VERTEXNUM;i++)
		dfscore(edge, i, vertexStatusArr);
	printf("\n");
}

void dfscore(int (*edge)[VERTEXNUM], int i, int* vertexStatusArr)
{
	if(vertexStatusArr[i] == 1)
		return;
	printf("%d ", i);
	vertexStatusArr[i] = 1;

	for(int j=0;j<VERTEXNUM;j++)
		if(edge[i][j] == 1)
			dfscore(edge, j , vertexStatusArr);
}

void display(int (*edge)[VERTEXNUM])
{
	for(int i=0;i<VERTEXNUM;i++)
	{
		for(int j=0;j<VERTEXNUM;j++)
			printf("%d ", edge[i][j]);
		printf("\n");
	}
}

void createGragh(int (*edge)[VERTEXNUM], int start, int end)
{
	edge[start][end] = 1;
}


int main()
{
	int i,j;
	int (*edge)[VERTEXNUM] = (int (*)[VERTEXNUM])malloc(sizeof(int)*VERTEXNUM*VERTEXNUM);
	for(i=0;i<VERTEXNUM;i++)
		for(j=0;j<VERTEXNUM;j++)
			edge[i][j] = 0;

	int* vertexStatusArr = (int*)malloc(sizeof(int)*VERTEXNUM);
	for(i=0;i<VERTEXNUM;i++)
		vertexStatusArr[i] = 0;

	display(edge);
	createGragh(edge, 0, 3);
	createGragh(edge, 0, 4);
	createGragh(edge, 3, 1);
	createGragh(edge, 3, 2);
	createGragh(edge, 4, 1);

	display(edge);

	dfs(edge, vertexStatusArr);
	free(edge);
	return 1;
}


//邻接表矩阵的深度优先遍历
#include <stdio.h>
#include <malloc.h>
#define VERTEXNUM 5

typedef struct edge{
	int vertex;
	struct edge *next;
}st_edge;

void createGragh(st_edge** edge, int start, int end);
void display(st_edge** edge);
void delGragh(st_edge** edge);
void dfs(st_edge** edge, int* vertexStatusArr);
void dfscore(st_edge** edge, int i, int* vertexStatusArr);


void dfs(st_edge** edge, int* vertexStatusArr)
{
	printf("DFS: ");
	int i;
	for(i=0;i<VERTEXNUM;i++)
		dfscore(edge, i, vertexStatusArr);
	printf("\n");
}

void dfscore(st_edge** edge, int i, int* vertexStatusArr)
{
	if(vertexStatusArr[i] == 1)
		return;
	printf("%d ", i);
	vertexStatusArr[i] = 1;

	st_edge* p = *(edge+i);
	while(p != NULL)
	{
		dfscore(edge, p->vertex, vertexStatusArr);
		p = p->next;
	}
}

void createGragh(st_edge** edge, int start, int end)
{
	st_edge* newedge = (st_edge*)malloc(sizeof(st_edge));
	newedge->vertex = end;
	newedge->next = NULL;

	edge = edge + start;
	while(*edge != NULL)
		edge = &((*edge)->next);
	*edge = newedge;
}

void display(st_edge** edge)
{
	int i;
	st_edge* p;
	for(i=0;i<VERTEXNUM;i++)
	{
		printf("%d: ", i);
		p = *(edge+i);
		while(p!=NULL)
		{
			printf("%d ", p->vertex);
			p = p->next;
		}
		printf("\n");
	}
}

void delGragh(st_edge** edge)
{
	int i;
	st_edge* p;
	st_edge* del;
	for(i=0;i<VERTEXNUM;i++)
	{
		p = *(edge+i);
		while(p!=NULL)
		{
			del = p;
			p = p->next;
			free(del);
		}
		edge[i] = NULL;
	}
	free(edge);
}

int main()
{
	st_edge** edge = (st_edge**)malloc(sizeof(st_edge*)*VERTEXNUM);
	int i;
	for(i=0;i<VERTEXNUM;i++)
		edge[i] = NULL;
	int *vertexStatusArr = (int*)malloc(sizeof(int)*VERTEXNUM);
	for(i=0;i<VERTEXNUM;i++)
		vertexStatusArr[i] = 0;

	createGragh(edge, 0, 3);
	createGragh(edge, 0, 4);
	createGragh(edge, 3, 1);
	createGragh(edge, 3, 2);
	createGragh(edge, 4, 1);

	display(edge);
	dfs(edge, vertexStatusArr);
	edge = NULL;
	free(vertexStatusArr);
	vertexStatusArr = NULL;
	return 1;
}


下一回再总结图的BFS和队列。


邻接矩阵是一种常见的的存储方式,可以用来实现深度遍历广度遍历。下面是C++实现邻接矩阵存储方式实现深度遍历广度遍历的示例代码: ```c++ #include <iostream> #include <queue> using namespace std; #define MaxVertexNum 100 // 最大顶点数设为100 #define INFINITY 65535 // 用65535来代表∞ typedef int Vertex; // 用顶点下标表示顶点,为整型 typedef int WeightType; // 边的权值设为整型 typedef char DataType; // 顶点存储的数据类型设为字符型 // 边的定义 typedef struct ENode *PtrToENode; struct ENode { Vertex V1, V2; // 有向边<V1, V2> WeightType Weight; // 权重 }; typedef PtrToENode Edge; // 的定义 typedef struct GNode *PtrToGNode; struct GNode { int Nv; // 顶点数 int Ne; // 边数 WeightType G[MaxVertexNum][MaxVertexNum]; // 邻接矩阵 DataType Data[MaxVertexNum]; // 存顶点的数据 }; typedef PtrToGNode MGraph; // 初始化一个有VertexNum个顶点但没有边的 Graph CreateGraph(int VertexNum) { MGraph Graph = new GNode; Graph->Nv = VertexNum; Graph->Ne = 0; // 初始化邻接矩阵 for (Vertex V = 0; V < Graph->Nv; V++) for (Vertex W = 0; W < Graph->Nv; W++) Graph->G[V][W] = INFINITY; return Graph; } // 插入边 void InsertEdge(MGraph Graph, Edge E) { Graph->G[E->V1][E->V2] = E->Weight; // 若是无向,还要插入边<V2, V1> Graph->G[E->V2][E->V1] = E->Weight; } // 深度优先遍历DFS bool Visited[MaxVertexNum] = { false }; // 访问标志数组 void DFS(MGraph Graph, Vertex V, void (*Visit)(Vertex)) { // 访问顶点V Visit(V); Visited[V] = true; // 对V的每个邻接点W递归调用DFS for (Vertex W = 0; W < Graph->Nv; W++) if (Graph->G[V][W] != INFINITY && !Visited[W]) DFS(Graph, W, Visit); } // 广度优先遍历BFS void BFS(MGraph Graph, Vertex S, void (*Visit)(Vertex)) { queue<Vertex> Q; Visit(S); Visited[S] = true; Q.push(S); while (!Q.empty()) { Vertex V = Q.front(); Q.pop(); for (Vertex W = 0; W < Graph->Nv; W++) if (Graph->G[V][W] != INFINITY && !Visited[W]) { Visit(W); Visited[W] = true; Q.push(W); } } } // 访问顶点,输出顶点的下标 void Visit(Vertex V) { cout << V << " "; } int main() { MGraph Graph = CreateGraph(5); Edge E = new ENode; E->V1 = 0; E->V2 = 1; E->Weight = 1; InsertEdge(Graph, E); E->V1 = 0; E->V2 = 2; E->Weight = 1; InsertEdge(Graph, E); E->V1 = 1; E->V2 = 2; E->Weight = 1; InsertEdge(Graph, E); E->V1 = 1; E->V2 = 3; E->Weight = 1; InsertEdge(Graph, E); E->V1 = 2; E->V2 = 4; E->Weight = 1; InsertEdge(Graph, E); E->V1 = 3; E->V2 = 4; E->Weight = 1; InsertEdge(Graph, E); cout << "DFS: "; DFS(Graph, 0, Visit); cout << endl; for (Vertex V = 0; V < Graph->Nv; V++) Visited[V] = false; // 重置访问标志 cout << "BFS: "; BFS(Graph, 0, Visit); cout << endl; return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值