Basic operations on graphs (adjacency matrix)

This article only has code, which introduces the basic operations on graphs (adjacency matrices).


It has been debugged without any major problems.
If there are mistakes, please criticize and correct.

1. The array (adjacency matrix) storage representation of the graph:

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

/* 状态信息 */
typedef int Status;
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0

/* 图的数组(邻接矩阵)存储表示 */
typedef int VRType;       //顶点关系类型
typedef char InfoType;    //弧类型
typedef char VertexType;  //顶点类型
#define INFINITY 0  //最大值∞
#define MAX_VERTEX_NUM 20 //最大顶点个数

typedef enum { DG, DN, UDG, UDN } GraphKind;//{有向图,有向网,无向图,无向网}

typedef struct ArcCell
{
	VRType adj;    //VRType是顶点关系类型。对无权图,用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;                 //图的种类标志 
}MGraph;

2. Basic operations on graphs:

/* 函数声明 */
Status CreateGraph(MGraph* G);/* 构造图CreateGraph(&G) */

Status CreateUDN(MGraph* G);/* 构造无向网CreateUDN(&G) */

Status CreateUDG(MGraph* G);/* 构造无向图CreateUDG(&G) */

Status CreateDN(MGraph* G);/* 构造有向网CreateDN(&G) */

Status CreateDG(MGraph* G);/* 构造有向图CreateDG(&G) */

void PrintGraph(MGraph G);/* 打印图PrintGraph(G) */

Status DestroyGraph(MGraph* G);/* 销毁图DestroyGraph(&G) */

Status LocateVex(MGraph G, VertexType u);/* 若图中存在顶点u,则返回该顶点在图中的位置LocateVex(G, u) */

Status GetVex(MGraph G, VertexType v);/* v是G的某个顶点,返回v的值GetVex(G, v) */

Status PutVex(MGraph* G, VertexType v, VertexType value);/* 对v赋值PutVex(&G, v, value) */

Status FirstAdjVex(MGraph G, VertexType v);/* 返回v的第一个邻接顶点FirstAdjVex(G, v) */

Status NextAdjVex(MGraph G, VertexType v, VertexType w);/* w是v的邻接顶点,返回v相对于w的下一个邻接顶点NextAdjVex(G, v, w) */

Status InsertVex(MGraph* G, VertexType v);/* 在图中增添新顶点InsertVex(&G, v) */

Status DeleteVex(MGraph* G, VertexType v);/* 删除G中顶点v及其相关的弧DeleteVex(&G, v) */

Status InsertArc(MGraph* G, VertexType v, VertexType w, VRType value);/* 在图中增添弧InsertArc(&G, v, w, value) */

Status DeleteArc(MGraph* G, VertexType v, VertexType w);/* 在图中删除弧DeleteArc(&G, v, w) */

/* DFS/BFS使用的全局变量 */
int visited[MAX_VERTEX_NUM];

void DFS(MGraph G, int n);/* 从第n个顶点出发深度优先遍历图DFS(G, n) */

void DFSTraverse(MGraph G);/* 对图G进行深度优先遍历DFSTraverse(G) */

void BFS(MGraph G, int n);/* 从第n个顶点出发广度优先遍历图BFS(G, n) */

void BFSTraverse(MGraph G);/* 对图G进行广度优先遍历BFSTraverse(G) */

1. Structural diagram:

/*---------------------------------------------------------------------------------------
功能:构造图
参数:1、图
输出:OK、ERROR
*/
/* 构造图CreateGraph(&G) */
Status CreateGraph(MGraph* G)
{
	printf("1.有向图 2.有向网 3.无向图 4.无向网\n");
	printf("请输入要创建表的种类:>");
	scanf("%d", &G->kind);
	switch (G->kind - 1)
	{
	case DG:
		return CreateDG(G);
	case DN:
		return CreateDN(G);
	case UDG:
		return CreateUDG(G);
	case UDN:
		return CreateUDN(G);
	default:
		break;
	}
	return ERROR;
}

2. Construct an undirected network:

/*---------------------------------------------------------------------------------------
功能:构造无向网
参数:1、图指针 
输出:OK、ERROR
*/
/* 构造无向网CreateUDN(&G) */
Status CreateUDN(MGraph* G)
{
	int i = 0, j = 0, k = 0, w = 0;
	char temp = 0;//临时储存
	printf("请输入图的顶点个数\n");
	scanf("%d", &G->vexnum);
	printf("请输入图的弧数\n");
	scanf("%d", &G->arcnum);
	printf("请输入所有顶点\n");
	for (i = 0; i < G->vexnum; i++)
	{
		temp = getchar();        //储存回车符
		scanf("%c", &G->vexs[i]);//将所有的顶点读入数组vexs中进行存储
	}
	//进行初始化,赋初值 
	for (i = 0; i < G->vexnum; i++)
	{
		for (j = 0; j < G->vexnum; j++)
		{
			G->arcs[i][j].adj = INFINITY;
			G->arcs[i][j].info = NULL;
		}
	}
	char v1, v2;
	printf("请输入弧的两个顶点和权值\n");
	//对矩阵进行赋值 
	for (k = 0; k < G->arcnum; k++)
	{
		temp = getchar();
		scanf("%c%c%d", &v1, &v2, &w);
		i = LocateVex(*G, v1);
		j = LocateVex(*G, v2);
		G->arcs[i][j].adj = w;
		G->arcs[j][i].adj = w;//对称 
	}
	printf("无向网创建成功!!!\n");
	return OK;
}

3. Construct an undirected graph:

/*---------------------------------------------------------------------------------------
功能:构造无向图
参数:1、图指针
输出:OK、ERROR
*/
/* 构造无向图CreateUDG(&G) */
Status CreateUDG(MGraph* G)
{
	int i = 0, j = 0, k = 0, w = 0;
	char temp = 0;//临时储存
	printf("请输入图的顶点个数\n");
	scanf("%d", &G->vexnum);
	printf("请输入图的弧数\n");
	scanf("%d", &G->arcnum);
	printf("请输入所有顶点\n");
	for (i = 0; i < G->vexnum; i++) 
	{
		temp = getchar();        //储存回车符
		scanf("%c", &G->vexs[i]);//将所有的顶点读入数组vexs中进行存储
	}
	//进行初始化,赋初值 
	for (i = 0; i < G->vexnum; i++) 
	{
		for (j = 0; j < G->vexnum; j++) 
		{
			G->arcs[i][j].adj = INFINITY;
			G->arcs[i][j].info = NULL;
		}
	}
	char v1, v2;
	printf("请输入弧的两个顶点\n");
	//对矩阵进行赋值 
	for (k = 0; k < G->arcnum; k++) 
	{
		temp = getchar();
		scanf("%c%c", &v1, &v2);
		i = LocateVex(*G, v1);
		j = LocateVex(*G, v2);
		G->arcs[i][j].adj = 1;
		G->arcs[j][i].adj = 1;//对称 
	}
	printf("无向图创建成功!!!\n");
	return OK;
}

4. Construct a directed network:

/*---------------------------------------------------------------------------------------
功能:构造有向网
参数:1、图指针
输出:OK、ERROR
*/
/* 构造有向网CreateDN(&G) */
Status CreateDN(MGraph* G)
{
	int i = 0, j = 0, k = 0, w = 0;
	char temp = 0;//临时储存
	printf("请输入图的顶点个数\n");
	scanf("%d", &G->vexnum);
	printf("请输入图的弧数\n");
	scanf("%d", &G->arcnum);
	printf("请输入所有顶点\n");
	for (i = 0; i < G->vexnum; i++)
	{
		temp = getchar();        //储存回车符
		scanf("%c", &G->vexs[i]);//将所有的顶点读入数组vexs中进行存储
	}
	//进行初始化,赋初值 
	for (i = 0; i < G->vexnum; i++)
	{
		for (j = 0; j < G->vexnum; j++)
		{
			G->arcs[i][j].adj = INFINITY;
			G->arcs[i][j].info = NULL;
		}
	}
	char v1, v2;
	printf("请输入弧的两个顶点(起点-终点)和权值\n");
	//对矩阵进行赋值 
	for (k = 0; k < G->arcnum; k++)
	{
		temp = getchar();
		scanf("%c%c%d", &v1, &v2, &w);
		i = LocateVex(*G, v1);
		j = LocateVex(*G, v2);
		G->arcs[i][j].adj = w;
	}
	printf("有向网创建成功!!!\n");
	return OK;
}

5. Construct a directed graph:

/*---------------------------------------------------------------------------------------
功能:构造有向图
参数:1、图指针
输出:OK、ERROR
*/
/* 构造有向图CreateDG(&G) */
Status CreateDG(MGraph* G)
{
	int i = 0, j = 0, k = 0, w = 0;
	char temp = 0;//临时储存
	printf("请输入图的顶点个数\n");
	scanf("%d", &G->vexnum);
	printf("请输入图的弧数\n");
	scanf("%d", &G->arcnum);
	printf("请输入所有顶点\n");
	for (i = 0; i < G->vexnum; i++)
	{
		temp = getchar();        //储存回车符
		scanf("%c", &G->vexs[i]);//将所有的顶点读入数组vexs中进行存储
	}
	//进行初始化,赋初值 
	for (i = 0; i < G->vexnum; i++)
	{
		for (j = 0; j < G->vexnum; j++)
		{
			G->arcs[i][j].adj = INFINITY;
			G->arcs[i][j].info = NULL;
		}
	}
	char v1, v2;
	printf("请输入弧的两个顶点(起点-终点)\n");
	//对矩阵进行赋值 
	for (k = 0; k < G->arcnum; k++)
	{
		temp = getchar();
		scanf("%c%c", &v1, &v2);
		i = LocateVex(*G, v1);
		j = LocateVex(*G, v2);
		G->arcs[i][j].adj = 1; 
	}
	printf("有向图创建成功!!!\n");
	return OK;
}

6. Print the picture:

/*---------------------------------------------------------------------------------------
功能:打印图
参数:1、图
输出:空
*/
/* 打印图PrintGraph(G) */
void PrintGraph(MGraph G)
{
	int i = 0, j = 0;
	for (i = 0; i < G.vexnum; ++i)
	{
		for (j = 0; j < G.vexnum; ++j)
		{
			printf("%d ", G.arcs[i][j].adj);
			if ((j + 1) % G.vexnum == 0)

				printf("\n");
		}
	}
}

7. Destruction map:

/*---------------------------------------------------------------------------------------
功能:销毁图
参数:1、图指针
输出:OK、ERROR
*/
/* 销毁图DestroyGraph(&G) */
Status DestroyGraph(MGraph* G)
{
	int i = 0, j = 0;
	for (i = 0; i < G->vexnum; i++) 
	{
		for (j = 0; j < G->vexnum; j++) 
		{
			G->arcs[i][j].adj = INFINITY;
			G->arcs[i][j].info = NULL;
		}
	}
	G->vexnum = 0;
	G->arcnum = 0;
	return OK;
}

8. If there is a vertex u in the graph, return the position of the vertex in the graph:

/*---------------------------------------------------------------------------------------
功能:若图中存在顶点u,则返回该顶点在图中的位置
参数:1、图 2、顶点
输出:顶点位置、FALSE
*/
/* 若图中存在顶点u,则返回该顶点在图中的位置LocateVex(G, u) */
Status LocateVex(MGraph G, VertexType u)
{
	int i = 0;
	for (i = 0; i < G.vexnum; i++) {
		if (G.vexs[i] == u)
			return i;
	}
	return FALSE;
}

9. v is a vertex of G, return the value of v:

/*---------------------------------------------------------------------------------------
功能:v是G的某个顶点,返回v的值
参数:1、图 2、顶点
输出:顶点的值、FALSWE
*/
/* v是G的某个顶点,返回v的值GetVex(G, v) */
Status GetVex(MGraph G, VertexType v)
{
	int i = 0;
	for (i = 0; i < G.vexnum; i++) 
	{
		if (G.vexs[i] == v)
			return i;
	}
	return FALSE;
}

10. Assign a value to v:

/*---------------------------------------------------------------------------------------
功能:对v赋值
参数:1、图指针 2、顶点 3、值
输出:OK、ERROR
*/
/* 对v赋值PutVex(&G, v, value) */
Status PutVex(MGraph* G, VertexType v, VertexType value)
{
	int i = 0;
	for (i = 0; i < G->vexnum; i++) 
	{
		if (G->vexs[i] == v)
			G->vexs[i] = value;
		return OK;
	}
	return ERROR;
}

11. Return the value of the first adjacent vertex of v:

/*---------------------------------------------------------------------------------------
功能:返回v的第一个邻接顶点的值
参数:1、图 2、顶点
输出:顶点、FALSE
*/
/* 返回v的第一个邻接顶点FirstAdjVex(G, v) */
Status FirstAdjVex(MGraph G, VertexType v)
{
	int i = 0, j = 0;
	i = LocateVex(G, v);
	for (j = 0; j < G.vexnum; j++) 
	{
		if (G.arcs[i][j].adj != INFINITY || G.arcs[j][i].adj != INFINITY)
		{
			return j;
		}
	}
	return FALSE;
}

12. w is the adjacent vertex of v, return the value of v relative to the next adjacent vertex of w:

/*---------------------------------------------------------------------------------------
功能:w是v的邻接顶点,返回v相对于w的下一个邻接顶点的值
参数:1、图 2、顶点 3、顶点
输出:顶点、FALSE
*/
/* w是v的邻接顶点,返回v相对于w的下一个邻接顶点NextAdjVex(G, v, w) */
Status NextAdjVex(MGraph G, VertexType v, VertexType w)
{
	int i = 0, j = 0, n = 0;
	i = LocateVex(G, v);
	j = LocateVex(G, w);
	for (n = j + 1; n < G.vexnum; n++) 
	{
		if (G.arcs[i][n].adj != INFINITY || G.arcs[n][i].adj != INFINITY)
		{
			return n;
		}
	}
	return FALSE;
}

13. Add new vertices to the graph:

/*---------------------------------------------------------------------------------------
功能:在图中增添新顶点
参数:1、图指针 2、顶点
输出:OK、ERROR
*/
/* 在图中增添新顶点InsertVex(&G, v) */
Status InsertVex(MGraph* G, VertexType v)
{
	int i = 0;
	G->vexnum++;
	//更改存储顶点的数组 
	G->vexs[G->vexnum - 1] = v;
	//更改矩阵
	for (i = 0; i < G->vexnum; i++) 
	{
		//为矩阵最外层行、列的元素赋初始值 
		G->arcs[G->vexnum - 1][i].adj = INFINITY;
		G->arcs[G->vexnum - 1][i].info = NULL;
		G->arcs[i][G->vexnum - 1].adj = INFINITY;
		G->arcs[i][G->vexnum - 1].info = NULL;
	}
	return OK;
}

14. Delete the vertex v and its associated arcs in G:

/*---------------------------------------------------------------------------------------
功能:删除G中顶点v及其相关的弧
参数:1、图指针 2、顶点
输出:OK、ERROR
*/
/* 删除G中顶点v及其相关的弧DeleteVex(&G, v) */
Status DeleteVex(MGraph* G, VertexType v)
{
	int i = 0, j = 0, temp = 0;
	i = LocateVex(*G, v);
	temp = i;
	//更改存储顶点的数组 
	for (temp; temp < G->vexnum; temp++) 
	{
		G->vexs[temp] = G->vexs[temp + 1];//存储顶点的数组中向前移一位,覆盖要删除的顶点 
	}
	G->vexnum--;
	//更改矩阵
	for (j = 0; j < G->vexnum + 1; j++) 
	{
		//使矩阵中靠后位置的顶点前移,覆盖被删除的顶点
		for (i; i < G->vexnum + 1; i++) 
		{
			G->arcs[j][i] = G->arcs[j][i + 1];
			G->arcs[i][j] = G->arcs[i + 1][j];
		}
	}
	for (i = 0; i < G->vexnum; i++) 
	{
		//上一步前移完成后矩阵的最外层的行、列的数据应被清除 
		G->arcs[G->vexnum][i].adj = INFINITY;
		G->arcs[G->vexnum][i].info = NULL;
		G->arcs[i][G->vexnum].adj = INFINITY;
		G->arcs[i][G->vexnum].info = NULL;
	}
	return OK;
}

15. Add arcs to the graph:

/*---------------------------------------------------------------------------------------
功能:在图中增添弧
参数:1、图指针 2、顶点 3、顶点 4、权值
输出:OK、ERROR
*/
/* 在图中增添弧InsertArc(&G, v, w, value) */
Status InsertArc(MGraph* G, VertexType v, VertexType w, VRType value)
{
	int i = 0, j = 0;
	i = LocateVex(*G, v);
	j = LocateVex(*G, w);
	G->arcs[i][j].adj = value;
	G->arcs[i][j].info = NULL;
	G->arcs[j][i].adj = value;
	G->arcs[j][i].info = NULL;
	return OK;
}

16. Delete arcs in the graph:

/*---------------------------------------------------------------------------------------
功能:在图中删除弧
参数:1、图指针 2、顶点 3、顶点
输出:OK、ERROR
*/
/* 在图中删除弧DeleteArc(&G, v, w) */
Status DeleteArc(MGraph* G, VertexType v, VertexType w)
{
	int i = 0, j = 0;
	i = LocateVex(*G, v);
	j = LocateVex(*G, w);
	G->arcs[i][j].adj = INFINITY;
	G->arcs[i][j].info = NULL;
	G->arcs[j][i].adj = INFINITY;
	G->arcs[j][i].info = NULL;
	return OK;
}

17. Depth-first traverse the graph starting from the nth vertex:

/*---------------------------------------------------------------------------------------
功能:从第n个顶点出发深度优先遍历图
参数:1、图 2、顶点位置
输出:空
*/
/* 从第n个顶点出发深度优先遍历图DFS(G, n) */
void DFS(MGraph G, int n)
{
	int i;
	printf("%c", G.vexs[n]);
	visited[n] = TRUE;
	for (i = 0; i < G.vexnum; i++) 
	{
		if (G.arcs[n][i].adj != INFINITY && visited[i] == FALSE)
		{
			DFS(G, i);
		}
	}
}

18. Depth-first traversal of graph G:

/*---------------------------------------------------------------------------------------
功能:对图G进行深度优先遍历
参数:1、图
输出:空
*/
/* 对图G进行深度优先遍历DFSTraverse(G) */
void DFSTraverse(MGraph G)
{
	int i = 0, n = 0;
	for (i = 0; i < G.vexnum; i++)
	{
		visited[i] = FALSE; //初始化标志数组 
	}
	for (n = 0; n < G.vexnum; n++) 
	{
		//因为图可能是非联通图,递归访问下一个顶点时可能会中断,因此需要从每一个顶点开始做深度优先遍历
		if (visited[n] == FALSE)//判断是否被访问过,未被访问过时访问 
		{
			DFS(G, n);
		}
	}
}

19. Breadth-first traverse the graph starting from the nth vertex:

/*---------------------------------------------------------------------------------------
功能:从第n个顶点出发广度优先遍历图
参数:1、图 2、顶点位置
输出:空
*/
/* 从第n个顶点出发广度优先遍历图BFS(G, n) */
void BFS(MGraph G, int n)
{
	int que[MAX_VERTEX_NUM], front = 0, rear = 0;
	int i = 0, w = 0;
	printf("%c", G.vexs[n]);
	visited[n] = TRUE;//访问 
	rear = (rear + 1) % MAX_VERTEX_NUM;//入队 
	que[rear] = n;
	while (front != rear) 
	{
		//队列不空时 
		front = (front + 1) % MAX_VERTEX_NUM;//出队 
		i = que[front];
		for (w = FirstAdjVex(G, G.vexs[i]); w != FALSE; w = NextAdjVex(G, G.vexs[i], G.vexs[w])) 
		{
			if (visited[w] == FALSE) 
			{
				visited[w] = TRUE;
				printf("%c", G.vexs[w]);//访问 
				rear = (rear + 1) % MAX_VERTEX_NUM;//入队 
				que[rear] = w;
			}
		}
	}
}

20. Perform breadth-first traversal on graph G:

 

/*---------------------------------------------------------------------------------------
功能:对图G进行广度优先遍历
参数:1、图
输出:空
*/
/* 对图G进行广度优先遍历BFSTraverse(G) */
void BFSTraverse(MGraph G)
{
	int i = 0, n = 0;
	for (i = 0; i < G.vexnum; i++)
	{
		visited[i] = FALSE; //初始化标志数组 
	}
	for (n = 0; n < G.vexnum; n++) 
	{
		//因为图可能是非联通图,递归访问下一个顶点时可能会中断,因此需要从每一个顶点开始做深度优先遍历
		if (visited[n] == FALSE)//判断是否被访问过,未被访问过时访问 
		{
			BFS(G, n);
		}
	}
}

3. Test the main program (take the undirected network as an example):

int main()
{
	MGraph G;
	int pos = 0,value = 0;
	VertexType v, w,p, q = 0;

	CreateGraph(&G);
	
	printf("邻接矩阵:\n");
	PrintGraph(G);

	v = 'a';
	pos = GetVex(G,v);
	printf("%c的位置是第%d个\n", v, pos);

	v = 'c';
	p = FirstAdjVex(G,v);
	printf("%c的第一个邻接顶点是%c\n", v, G.vexs[p]);

	v = 'c';
	w = 'b';
	p = NextAdjVex(G,v,w);
	printf("%c相对于%c的下一个邻接顶点是%c\n", v, w, G.vexs[p]);

	v = 'd';
	w = 'e';
	value = 1;
	if (InsertArc(&G, v, w, value))
	{
		printf("成功插入<%c,%c,%d>\n", v, w, value);
	}
	printf("邻接矩阵:\n");
	PrintGraph(G);

	v = 'd';
	w = 'e';
	if (DeleteArc(&G, v, w))
	{
		printf("成功删除弧<%c,%c>\n", v, w);
	}

	printf("邻接矩阵:\n");
	PrintGraph(G);

	printf("深度优先遍历DFS:\n");
	DFSTraverse(G);
	printf("\n");

	printf("广度优先遍历BFS:\n");
	BFSTraverse(G);
	printf("\n");

	if (DestroyGraph(&G))
	{
		printf("销毁成功!!!\n");
	}
	
	system("pause");
	return 0;
}

4. Test results:

 

Guess you like

Origin blog.csdn.net/absorb2601078490/article/details/125526924