数据结构---图的邻接矩阵(创建,打印,深度优先遍历,广度优先遍历,C语言)

 

邻接矩阵法

  用一维数组图中顶点的信息,用一个二维数组存储图中边的信息(各顶点之间的邻接关系)。存储顶点之间邻接关系的二维数组称为邻接矩阵

     结点数为n的图G=(V,E)的邻接矩阵A是n*n的,将G的顶点编号为v1,v2,......vn。若(vi,vj)∈E,则A[i][j]=1,否则A[i][j]=0。

 

对于带权图而言,若顶点vi,vj之间有边相连,则邻接矩阵中对应项存放着该边对应的权值,若顶点vi和vj不相连,则用∞来表示这两个顶点之间不存在边

无向图的邻接矩阵表示:

有向图的邻接矩阵表示

网的邻接矩阵表示(网就是带权的图)

 无向图

#include <stdio.h>
#include <string.h>
#define MaxVertexNum  100   //顶点数目最大值
typedef char VertexType;   //顶点的数据类型
typedef int EdgeType;     //带权图中边上权值的数据类型

typedef struct
{
	VertexType Vex[MaxVertexNum];   //顶点表
	EdgeType Edge[MaxVertexNum][MaxVertexNum];  //邻接矩阵,边表
	int vexnum, edgenum;    //图的顶点数和弧数
}MGraph;

/**********创建无向图**********/
void create_Graph(MGraph *G)
{
	int i, j;
	int start, end;  //边的起点序号、终点序号
	int numV, numE;
	int w;   //边上的权值
	printf("请输入所创建无向图的顶点数和边数(用空格隔开):");
	scanf_s("%d%d", &numV, &numE);
	G->vexnum=numV;
	G->edgenum=numE;
	
	printf("\n");
	//图的初始化
	for (i = 0; i < G->vexnum; i++)
	{
		for (j = 0; j < G->vexnum; j++)
		{
			if (i == j)
				G->Edge[i][j] = 0;
			else
				G->Edge[i][j] = 32767;
		}
	}

	//顶点信息存入顶点表
	for (i = 0; i < G->vexnum; i++)
	{
		printf("请输入第%d个顶点的信息:",i+1);
		scanf_s("%d", &G->Vex[i]);
	}
	printf("\n");
	//输入无向图边的信息
	for (i = 0; i < G->edgenum; i++)
	{
		printf("请输入边的起点序号,终点序号,权值(用空格隔开):");
		scanf_s("%d%d%d", &start, &end, &w);
		G->Edge[start -1][end -1] = w;
		G->Edge[end - 1][start - 1] = w;   //无向图具有对称性
	}
}

/***********打印出邻接矩阵*********/
void print_Matrix(MGraph G)
{
	int i, j;
	printf("\n图的顶点为:");
	for (i = 0; i < G.vexnum; i++)
		printf("%d ", G.Vex[i]);
	printf("\n输出邻接矩阵:\n");
	printf("\t");
	for (i = 0; i < G.vexnum; i++)
		printf("\t%8d", G.Vex[i]);
		
	for (i = 0; i < G.vexnum; i++)
	{
		printf("\n\n%8d", G.Vex[i]);
		for (j = 0; j < G.vexnum; j++)
		{
			if (G.Edge[i][j] == 32767)
				printf("\t%8s", "∞");
			else
				printf("\t%8d", G.Edge[i][j]);
		}
		printf("\n");
	}	
}

void main()
{
	MGraph G;
	create_Graph(&G);
	print_Matrix(G);
	system("pause");
}

运行结果如下:

有向图

代码基本是一样的,只是对称的位置上权值不一样

/***********创建有向图************/
void create_Graph2(MGraph *G)
{
	int i, j;
	int start, end;  //边的起点序号、终点序号
	int numV, numE;
	int w;   //边上的权值
	printf("请输入所创建有向图的顶点数和边数(用空格隔开):");
	scanf_s("%d%d", &numV, &numE);
	G->vexnum = numV;
	G->edgenum = numE;

	printf("\n");
	//图的初始化
	for (i = 0; i < G->vexnum; i++)
	{
		for (j = 0; j < G->vexnum; j++)
		{
			if (i == j)
				G->Edge[i][j] = 0;
			else
				G->Edge[i][j] = 32767;
		}
	}

	//顶点信息存入顶点表
	for (i = 0; i < G->vexnum; i++)
	{
		printf("请输入第%d个顶点的信息:", i + 1);
		scanf_s("%d", &G->Vex[i]);
	}
	printf("\n");
	//输入无向图边的信息
	for (i = 0; i < G->edgenum; i++)
	{
		printf("请输入边的起点序号,终点序号,权值(用空格隔开):");
		scanf_s("%d%d%d", &start, &end, &w);
		G->Edge[start - 1][end - 1] = w;   //有向图只在这里不一样
	}
}

深度优先遍历

/**********深度优先遍历*********/
int visitDFS[maxSize];
void DFS(MGraph G,int i)
{
	int j;
	visitDFS[i] = 1;
	printf("%d ", G.Vex[i]);
	for (j = 0; j < G.vexnum; j++)
	{
		if (G.Edge[i][j] != 32767 && !visitDFS[j])
			DFS(G, j);
	}
}

void DFSTraverse(MGraph G)
{
	int i;
	for (i = 0; i < G.vexnum; i++)
		visitDFS[i] = 0;
	for (i = 0; i < G.vexnum; i++)
	{
		if (!visitDFS[i])
			DFS(G, i);
	}
}

 

深度优先遍历

/**********深度优先遍历*********/
int visitDFS[maxSize];
void DFS(MGraph G,int i)
{
	int j;
	visitDFS[i] = 1;
	printf("%d ", G.Vex[i]);
	for (j = 0; j < G.vexnum; j++)
	{
		if (G.Edge[i][j] != 32767 && !visitDFS[j])
			DFS(G, j);
	}
}

void DFSTraverse(MGraph G)
{
	int i;
	for (i = 0; i < G.vexnum; i++)
		visitDFS[i] = 0;
	for (i = 0; i < G.vexnum; i++)
	{
		if (!visitDFS[i])
			DFS(G, i);
	}
}

广度优先遍历

/**************广度优先遍历*************/
//队列
typedef struct
{
	int data[maxSize];
	int front, rear;
}Queue;

//初始化
void InitQueue(Queue *Q)
{
	Q->front = Q->rear = 0;
}

//判断队空
int IsEmpty(Queue *Q)
{
	if (Q->front == Q->rear)
		return 1;
	else
		return 0;
}

//入队
void EnQueue(Queue *Q,int e)
{
	if ((Q->rear + 1) % maxSize == Q->front)
		return;
	else
	{
		Q->data[Q->rear] = e;
		Q->rear = (Q->rear + 1) % maxSize;
	}
}
//出队
void DeQueue(Queue *Q,int *e)
{
	if (Q->rear == Q->front)
		return;
	*e = Q->data[Q->front];
	Q->front = (Q->front + 1) % maxSize;
}
//广度优先遍历
int visitBFS[maxSize];
void BFS(MGraph G)
{
	int i, j;
	Queue Q;
	for (i = 0; i < G.vexnum; i++)
		visitBFS[maxSize] = 0;
	InitQueue(&Q);
	for (i = 0; i < G.vexnum; i++)
	{
		if (!visitBFS[i])
		{
			visitBFS[i] = 1;
			printf("%d ", G.Vex[i]);
			EnQueue(&Q, i);

			while (!IsEmpty(&Q))
			{
				DeQueue(&Q, &i);
				for (j = 0; j < G.vexnum; j++)
				{
					if (!visitBFS[j] && G.Edge[i][j] != 32767)
					{
						visitBFS[j] = 1;
						printf("%d ", G.Vex[j]);
						EnQueue(&Q, j);
					}
				}
			}
		}
	}
}

 

  • 89
    点赞
  • 417
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
邻接矩阵实现深度优先遍历广度优先遍历深度优先遍历: 1. 定义一个栈,将起始节点入栈。 2. 当栈不为空时,取出栈顶节点,访问该节点,并将其未被访问的邻居节点入栈。 3. 标记已访问的节点。 4. 重复步骤2和3,直到栈为空。 邻接矩阵实现深度优先遍历的代码: ```c #define MAX_VERTEX_NUM 100 //最大顶点数 #define INFINITY 65535 //表示无穷大 typedef struct { int vexs[MAX_VERTEX_NUM]; //顶点表 int arcs[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; //邻接矩阵 int vexnum, arcnum; //的当前顶点数和弧数 } MGraph; int visited[MAX_VERTEX_NUM]; //标记节点是否被访问过 void DFS(MGraph G, int v) { visited[v] = 1; //标记节点v已被访问 printf("%d ", G.vexs[v]); //访问节点v for (int i = ; i < G.vexnum; i++) { if (G.arcs[v][i] != INFINITY && !visited[i]) { //如果节点i是节点v的邻居且未被访问 DFS(G, i); //递归访问节点i } } } void DFSTraverse(MGraph G) { for (int i = ; i < G.vexnum; i++) { visited[i] = ; //初始化visited数组 } for (int i = ; i < G.vexnum; i++) { if (!visited[i]) { //如果节点i未被访问 DFS(G, i); //从节点i开始深度优先遍历 } } } ``` 广度优先遍历: 1. 定义一个队列,将起始节点入队。 2. 当队列不为空时,取出队首节点,访问该节点,并将其未被访问的邻居节点入队。 3. 标记已访问的节点。 4. 重复步骤2和3,直到队列为空。 邻接矩阵实现广度优先遍历的代码: ```c #define MAX_VERTEX_NUM 100 //最大顶点数 #define INFINITY 65535 //表示无穷大 typedef struct { int vexs[MAX_VERTEX_NUM]; //顶点表 int arcs[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; //邻接矩阵 int vexnum, arcnum; //的当前顶点数和弧数 } MGraph; int visited[MAX_VERTEX_NUM]; //标记节点是否被访问过 void BFS(MGraph G, int v) { int queue[MAX_VERTEX_NUM]; //定义队列 int front = , rear = ; //队首和队尾指针 visited[v] = 1; //标记节点v已被访问 printf("%d ", G.vexs[v]); //访问节点v queue[rear++] = v; //将节点v入队 while (front != rear) { //队列不为空时 int w = queue[front++]; //取出队首节点w for (int i = ; i < G.vexnum; i++) { if (G.arcs[w][i] != INFINITY && !visited[i]) { //如果节点i是节点w的邻居且未被访问 visited[i] = 1; //标记节点i已被访问 printf("%d ", G.vexs[i]); //访问节点i queue[rear++] = i; //将节点i入队 } } } } void BFSTraverse(MGraph G) { for (int i = ; i < G.vexnum; i++) { visited[i] = ; //初始化visited数组 } for (int i = ; i < G.vexnum; i++) { if (!visited[i]) { //如果节点i未被访问 BFS(G, i); //从节点i开始广度优先遍历 } } } ``` 邻接表实现深度优先遍历广度优先遍历深度优先遍历: 1. 定义一个栈,将起始节点入栈。 2. 当栈不为空时,取出栈顶节点,访问该节点,并将其未被访问的邻居节点入栈。 3. 标记已访问的节点。 4. 重复步骤2和3,直到栈为空。 邻接表实现深度优先遍历的代码: ```c #define MAX_VERTEX_NUM 100 //最大顶点数 typedef struct ArcNode { //边表节点 int adjvex; //邻接点在顶点表中的位置 struct ArcNode *nextarc; //指向下一个边表节点 } ArcNode; typedef struct VNode { //顶点表节点 int data; //顶点数据 ArcNode *firstarc; //指向第一个边表节点 } VNode, AdjList[MAX_VERTEX_NUM]; typedef struct { AdjList vertices; //邻接表 int vexnum, arcnum; //的当前顶点数和弧数 } ALGraph; int visited[MAX_VERTEX_NUM]; //标记节点是否被访问过 void DFS(ALGraph G, int v) { visited[v] = 1; //标记节点v已被访问 printf("%d ", G.vertices[v].data); //访问节点v ArcNode *p = G.vertices[v].firstarc; while (p) { if (!visited[p->adjvex]) { //如果节点p->adjvex未被访问 DFS(G, p->adjvex); //递归访问节点p->adjvex } p = p->nextarc; } } void DFSTraverse(ALGraph G) { for (int i = ; i < G.vexnum; i++) { visited[i] = ; //初始化visited数组 } for (int i = ; i < G.vexnum; i++) { if (!visited[i]) { //如果节点i未被访问 DFS(G, i); //从节点i开始深度优先遍历 } } } ``` 广度优先遍历: 1. 定义一个队列,将起始节点入队。 2. 当队列不为空时,取出队首节点,访问该节点,并将其未被访问的邻居节点入队。 3. 标记已访问的节点。 4. 重复步骤2和3,直到队列为空。 邻接表实现广度优先遍历的代码: ```c #define MAX_VERTEX_NUM 100 //最大顶点数 typedef struct ArcNode { //边表节点 int adjvex; //邻接点在顶点表中的位置 struct ArcNode *nextarc; //指向下一个边表节点 } ArcNode; typedef struct VNode { //顶点表节点 int data; //顶点数据 ArcNode *firstarc; //指向第一个边表节点 } VNode, AdjList[MAX_VERTEX_NUM]; typedef struct { AdjList vertices; //邻接表 int vexnum, arcnum; //的当前顶点数和弧数 } ALGraph; int visited[MAX_VERTEX_NUM]; //标记节点是否被访问过 void BFS(ALGraph G, int v) { int queue[MAX_VERTEX_NUM]; //定义队列 int front = , rear = ; //队首和队尾指针 visited[v] = 1; //标记节点v已被访问 printf("%d ", G.vertices[v].data); //访问节点v queue[rear++] = v; //将节点v入队 while (front != rear) { //队列不为空时 int w = queue[front++]; //取出队首节点w ArcNode *p = G.vertices[w].firstarc; while (p) { if (!visited[p->adjvex]) { //如果节点p->adjvex未被访问 visited[p->adjvex] = 1; //标记节点p->adjvex已被访问 printf("%d ", G.vertices[p->adjvex].data); //访问节点p->adjvex queue[rear++] = p->adjvex; //将节点p->adjvex入队 } p = p->nextarc; } } } void BFSTraverse(ALGraph G) { for (int i = ; i < G.vexnum; i++) { visited[i] = ; //初始化visited数组 } for (int i = ; i < G.vexnum; i++) { if (!visited[i]) { //如果节点i未被访问 BFS(G, i); //从节点i开始广度优先遍历 } } } ```
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值