数据结构-图的实现以及基础算法-C语言实现

Posted OpenAll_Zzz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构-图的实现以及基础算法-C语言实现相关的知识,希望对你有一定的参考价值。

0. 必要的说明

  • 由于是用C语言编写并且图这一章中代码复用性很强,所以在写的时候都是建立工程分文件来写的,考虑一部分同学的特殊需要,笔者重新组织了所有的源文件(xxx.c)和头文件(xxx.h),并成为一个源文件,方便大家利用。最后考虑到在进行编译源文件和链接到相关的函数、变量以及声明时的顺序被无意打乱,程序可能跑不过,这种情况按下面红字操作。
  • 有需要查看工程文件的伙伴可以点击这里进入代码仓库下载。
  • 如果你的编译器是VS2019或者以往版本,那么你只需要复制一份代码到你的VS2019上再按下Fn + F5即可;如果你的编译器是CodeBlocks或者Dev C++等等其他的,那么你需要将每一个程序的第一行代码#define _CRT_SECURE_NO_WARNINGS 1删除后再将代码复制到你的编译器上运行。
  • 你的支持和鼓励是我创作的最大动力😉!

1. 图的实现

 1.1 图的邻接矩阵实现

#define _CRT_SECURE_NO_WARNINGS 1

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

// 图的结点的数据类型为Char
typedef char VertexDataType;
// 边的权值类型为Int
typedef int EdgeWeightDataType;

typedef struct 
	VertexDataType* setsOfVertex; // 一维数组存储顶点的值
	EdgeWeightDataType** AdjacencyMatrix; // 二维数组表示邻接矩阵
	int numsOfVertex; // 顶点的个数
	int numsOfEdge;  // 边的条数
	int MaxSizeCnt; // 限制顶点的最大个数
MatrixGraph; // 邻接矩阵表示图的结构

void InitGraph(MatrixGraph* Graph, int n); // 初始化图的结构

void InsertVertex(MatrixGraph* Graph, VertexDataType vertex); // 在图中插入顶点

void InsertEdge(MatrixGraph* Graph, int v1, int v2, EdgeWeightDataType weight); // 添加顶点间的联系

void ShowMatrix(MatrixGraph* Graph); // 显示图的邻接矩阵表示

int main() 

	MatrixGraph graph;
	InitGraph(&graph, 5);
	// 添加顶点
	InsertVertex(&graph, 'A'); // index 0
	InsertVertex(&graph, 'B'); // index 1
	InsertVertex(&graph, 'C'); // index 2
	InsertVertex(&graph, 'D'); // index 3
	InsertVertex(&graph, 'E'); // index 4
	// 添加顶点间的关系
	InsertEdge(&graph, 0, 1, 1);
	InsertEdge(&graph, 0, 3, 1);
	InsertEdge(&graph, 1, 2, 1);
	InsertEdge(&graph, 1, 4, 1);
	InsertEdge(&graph, 2, 3, 1);
	InsertEdge(&graph, 2, 4, 1);

	// 展示无向图的邻接矩阵
	ShowMatrix(&graph);
	return 0;


// 初始化图的结构
void InitGraph(MatrixGraph* Graph, int n) 
	Graph->setsOfVertex = (VertexDataType*)malloc(sizeof(VertexDataType) * n);
	Graph->AdjacencyMatrix = (EdgeWeightDataType**)malloc(sizeof(int*) * n);
	for (int i = 0; i < n; i++) 
		Graph->AdjacencyMatrix[i] = (EdgeWeightDataType*)malloc(sizeof(EdgeWeightDataType) * n);
	

	for (int i = 0; i < n; i++) 
		for (int j = 0; j < n; j++) 
			Graph->AdjacencyMatrix[i][j] = 0;
		
	
	Graph->numsOfEdge = 0;
	Graph->numsOfVertex = 0;
	Graph->MaxSizeCnt = n;


// 在图中插入顶点
void InsertVertex(MatrixGraph* Graph, VertexDataType vertex) 
	if (Graph->numsOfVertex <= Graph->MaxSizeCnt) 
		Graph->setsOfVertex[Graph->numsOfEdge] = vertex;
		Graph->numsOfVertex++;
	


// 添加顶点间的联系
void InsertEdge(MatrixGraph* Graph, int v1, int v2, EdgeWeightDataType weight) 
	Graph->AdjacencyMatrix[v1][v2] = weight;
	Graph->AdjacencyMatrix[v2][v1] = weight;
	Graph->numsOfEdge++;


// 显示图的邻接矩阵表示
void ShowMatrix(MatrixGraph* Graph) 
	printf("\\n\\n\\n");
	for (int i = 0; i < Graph->numsOfVertex; i++) 
		printf("       [ ");
		for (int j = 0; j < Graph->numsOfVertex; j++) 
			if (j != Graph->numsOfVertex - 1) 
				printf("%d ", Graph->AdjacencyMatrix[i][j]);
			
			else 
				printf("%d ", Graph->AdjacencyMatrix[i][j]);
			
		
		printf("]");
		printf("\\n");
	

 1.2 图的邻接表实现

#define _CRT_SECURE_NO_WARNINGS 1
#define MAX_VERTEXNUMS 70 // 最大顶点个数
#include <stdio.h>
#include <stdlib.h>

typedef char VertexDataType; // 顶点所储存数据的类型
typedef int EdgeWeightDataType; // 边的权值类型

// 边结点(的结构)
typedef struct GraphEdgeNode 
	int adjVertexIndex; // 邻接结点的索引
	struct GraphEdgeNode* p_nextEdge; // 下一条边的地址
	EdgeWeightDataType infoOfEdge; // 边的信息
EdgeNode;

// 顶点(的结构)
typedef struct GraphVertexNode 
	VertexDataType val;
	EdgeNode* p_firstAdjEdge; // 指向第一条邻接该顶点的边
VertexNode;

// 邻接表所表示的图所包含的信息
typedef struct 
	VertexNode* setsOfVertex; // 每个顶点所表示的关系表
	int vertexNums; // 图中顶点数
	int edgeNums;  // 图中所存在的关系(边)的个数
ALGraph;

void BuildALGraph(ALGraph* graph); // 采用邻接表法构建无向图

int SearchVertexRetIndex(ALGraph* graph, VertexDataType val); // 在图中寻找值为val的顶点的索引

void showALGraph(ALGraph* graph); // 显示邻接表中的信息

#define _CRT_SECURE_NO_WARNINGS 1

#include "GraphOperationsStatement.h"

int main() 
	ALGraph graph;
	BuildALGraph(&graph);
	showALGraph(&graph);
	return 0;


// 采用邻接表法构建无向图
void BuildALGraph(ALGraph* graph) 
	graph->setsOfVertex = (VertexNode*)malloc(sizeof(VertexNode) * MAX_VERTEXNUMS);

	int vertexNums = 0;
	int edgeNums = 0;
	printf("分别输入顶点和边的个数(num1 num2):\\n");
	scanf("%d %d", &vertexNums, &edgeNums);
	getchar();

	graph->vertexNums = vertexNums;
	graph->edgeNums = edgeNums;

	// 输入图中各个顶点的信息
	for (int i = 0; i < graph->vertexNums; i++) 
		printf("输入第%d个顶点的信息:\\n", i + 1);
		scanf("%c", &(graph->setsOfVertex[i].val));
		getchar();
		graph->setsOfVertex[i].p_firstAdjEdge = NULL;
	

	// 输入各个边,构建邻接表
	VertexDataType v1 = 0;
	VertexDataType v2 = 0;
	int v1Index = 0;
	int v2Index = 0;
	for (int i = 0; i < graph->edgeNums; i++) 
		printf("输入第%d条边所依附的两个结点:\\n", i + 1);
		scanf("%c", &v1);
		getchar();
		scanf("%c", &v2);
		getchar();

		v1Index = SearchVertexRetIndex(graph, v1);
		v2Index = SearchVertexRetIndex(graph, v2);

		EdgeNode* newEdgeNode0 = (EdgeNode*)malloc(sizeof(EdgeNode));
		newEdgeNode0->adjVertexIndex = v2Index;
		newEdgeNode0->p_nextEdge = graph->setsOfVertex[v1Index].p_firstAdjEdge;
		graph->setsOfVertex[v1Index].p_firstAdjEdge = newEdgeNode0;

		EdgeNode* newEdgeNode1 = (EdgeNode*)malloc(sizeof(EdgeNode));
		newEdgeNode1->adjVertexIndex = v1Index;
		newEdgeNode1->p_nextEdge = graph->setsOfVertex[v2Index].p_firstAdjEdge;
		graph->setsOfVertex[v2Index].p_firstAdjEdge = newEdgeNode1;
	


// 在图中寻找值为val的顶点的索引
int SearchVertexRetIndex(ALGraph* graph, VertexDataType val) 

	for (int i = 0; i < graph->vertexNums; i++) 
		if (graph->setsOfVertex[i].val == val) 
			return i;
		
	

	return -1;


// 显示邻接表中的信息
void showALGraph(ALGraph* graph) 
	EdgeNode* cur = NULL;
	printf("\\n");
	for (int i = 0; i < graph->vertexNums; i++) 
		printf("%c->", graph->setsOfVertex[i].val);
		cur = graph->setsOfVertex[i].p_firstAdjEdge;
		while (cur != NULL) 
			printf("%d->", cur->adjVertexIndex);
			cur = cur->p_nextEdge;
		
		printf("NULL\\n");
	


2. 图的基础算法

 2.1 图的深度优先遍历

#define _CRT_SECURE_NO_WARNINGS 1
#define MAX_SIZEOFVERTEX 70

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

typedef int VertexDataType; // 顶点所储存数据的类型
typedef int EdgeWeightDataType; // 边的权值类型

// 边结点(的结构)
typedef struct GraphEdgeNode 
	int adjVertexIndex; // 邻接结点的索引
	struct GraphEdgeNode* p_nextEdge; // 下一条边的地址
	EdgeWeightDataType infoOfEdge; // 边的信息
EdgeNode;

// 顶点(的结构)
typedef struct GraphVertexNode 
	VertexDataType val;
	EdgeNode* p_firstAdjEdge; // 指向第一条邻接该顶点的边
VertexNode;

// 邻接表所表示的图所包含的信息
typedef struct 
	VertexNode* setsOfVertex; // 每个顶点所表示的关系表
	int vertexNums; // 图中顶点数
	int edgeNums;  // 图中所存在的关系(边)的个数
	int* visited; // 图中顶点是否被访问过的的标志数组
ALGraph;

void InitALGraph(ALGraph* graph); // 初始化无向图

void InsertVertex(ALGraph* graph, VertexDataType val); // 插入值为val的顶点

void InsertEdge(ALGraph* graph, VertexDataType val_1, VertexDataType val_2); // 插入依附顶点val1和val2的边

int SearchVertexRetIndex(ALGraph* graph, VertexDataType val); // 在图中寻找值为val的顶点的索引

void showALGraph(ALGraph* graph); // 显示邻接表中的信息

void DFS_AL(ALGraph* graph, int StartVertexIndex); // 对无向图进行深度优先遍历

int main() 
	ALGraph graph;
	InitALGraph(&graph);

	InsertVertex(&graph, 1);
	InsertVertex(&graph, 2);
	InsertVertex(&graph, 3);
	InsertVertex(&graph, 4);
	InsertVertex(&graph, 5);
	InsertVertex(&graph, 6);
	InsertVertex(&graph, 7);

	InsertEdge(&graph, 1, 3);
	InsertEdge(&graph, 1, 2);
	InsertEdge(&graph, 3, 2);
	InsertEdge(&graph, 2, 5);
	InsertEdge(&graph, 2, 4);
	InsertEdge(&graph, 5, 7);
	InsertEdge(&graph, 5, 6);
	showALGraph(&graph);

	printf("无向连通图的优先深度遍历结果:\\n");
	DFS_AL(&graph, 0);
	return 0;


// 初始化无向图
void InitALGraph(ALGraph* graph) 
	graph->setsOfVertex = (VertexNode*)malloc(sizeof(VertexNode) * MAX_SIZEOFVERTEX );
	graph->edgeNums = 0;
	graph->vertexNums = 0;

	graph->visited = (int*)malloc(sizeof(int) * MAX_SIZEOFVERTEX );


// 插入值为val的顶点
void InsertVertex(ALGraph* graph, VertexDataType val) 
	graph->setsOfVertex[graph->vertexNums].val = val;
	graph->setsOfVertex[graph->vertexNums].p_firstAdjEdge = NULL;
	graph->visited[graph->vertexNums] = 0;// 初始化插入时的结点未被访问
	graph->vertexNums++;


// 插入依附顶点val1和val2的边
void InsertEdge(ALGraph* graph, VertexDataType val_1, VertexDataType val_2) 
	int v1Index = 0;
	int v2Index = 0;

	v1Index = SearchVertexRetIndex(graph, val_1);
	v2Index = SearchVertexRetIndex(graph, val_2);


	// 无向图需要关联到一条边所依附的两个顶点,即联系X->Y的同时,也需要联系Y->X

	// 头插结点来构建每个顶点的邻接关系

	// X->Y
	EdgeNode* newEdgeNode0 = (EdgeNode*)malloc(sizeof(EdgeNode));
	if (newEdgeNode0 == NULL) 
		exit(0);
	
	newEdgeNode0->adjVertexIndex = v2Index;
	newEdgeNode0->p_nextEdge = graph->setsOfVertex[v1Index].p_firstAdjEdge;
	graph->setsOfVertex[v1Index].p_firstAdjEdge = newEdgeNode0;

	// Y->X
	EdgeNode* newEdgeNode1 = (EdgeNode*)malloc(sizeof(EdgeNode));
	if (newEdgeNode1 == NULL) 
		exit(0);
	
	newEdgeNode1->adjVertexIndex = v1Index;
	newEdgeNode1->p_nextEdge = graph->setsOfVertex[v2Index].p_firstAdjEdge;
	graph->setsOfVertex[v2Index].p_firstAdjEdge = newEdgeNode1;

	graph->edgeNums++;


以上是关于数据结构-图的实现以及基础算法-C语言实现的主要内容,如果未能解决你的问题,请参考以下文章

C语言实现图的广度优先搜索遍历算法

图的遍历和生成树求解实现 (c语言版)

数据结构C语言版 图的遍历 DFS和BFS算法,用邻接矩阵储存 急阿在线等 求大神指点

求算法,用邻接矩阵和邻接表创建一个图,实现深度和广度搜索,菜单形式,c语言的代码。无向无权的图。

Dijkstra算法的C语言实现:文件读取、图的存储、算法实现、路径输出

数据结构与算法拓扑排序问题C语言实现