一、图的存储结构

1.邻接矩阵

设图G有n个顶点,则邻接矩阵是一个n*n的方阵,定义为

实例如下,左图是一个无向图,有图是邻接矩阵表示:

看一个有向图案例:

网图:每条边都带权的图叫做网。设图G是网图,有n个顶点,则邻接矩阵是一个n*n的方阵,定义为:

2.邻接表

邻接矩阵是一种不错的图存储结构,但是,对于边数相对顶点较少的图,这种存储结构存在存储空间的极大浪费。因此找到一种数组与链表相结合的存储方法称为邻接表。

邻接表的处理方法是这样的:

(1)图中顶点用一个一维数组存储,当然,顶点也可以用单链表存储,不过,数组可以较容易的读取顶点的信息,更加方便。

(2)图中每个顶点vi的所有邻接点构成一个线性表,由于邻接点的个数不定,所以,用单链表存储,无向图称为顶点vi的边表,有向图称为顶点vi作为弧尾的出边表。

例如,下图就是一个无向图的邻接表的结构。

从图中可以看出,顶点表的各个顶点由data和firstedge两个域表示,data是数据域,存储顶点的信息,firstedge是指针域,指向边表的第一个结点,即此顶点的第一个邻接表。边表结点有adjvex和next两个域组成。adjvex是邻接点域,存储某顶点的邻接点在顶点表中的下标,next则存储指向边表中下一个结点的指针。

若是有向图,邻接表的结构是类似的,邻接表和逆邻接表如下图所示:

对于带权的网图,可以在边表结点定义中再增加一个weight的数据域,存储权值信息即可,如下图所示:

图的邻接矩阵:

//无向带权图的邻接矩阵表示法
//初始化:所有边的值为初始化为无穷大,
//图创建好之后,顶点到自身顶点,顶点之间没有边的值都是无穷大,没有0。0是用在无权图中。
#include<stdio.h>
#include<stdlib.h>//INT_MAX在其中定义,这一行不能少

#define MAX_VERTEX 20//根据需要定义
#define INFINITY  INT_MAX

typedef int bool;
#define true 1
#define false 0

int visited[MAX_VERTEX];


typedef struct Graph
{
	char vertex[MAX_VERTEX];
	int edge[MAX_VERTEX][MAX_VERTEX];
	int vertex_nums, edge_nums;
}MGraph;

void CreateMGraph(MGraph *g)
{
	printf("请输入要创建的图的顶点数和边数:\n");
	scanf("%d,%d", &g->vertex_nums, &g->edge_nums);
	for (int i = 0; i < g->vertex_nums; i++)
	{
		printf("请输入第%d顶点的值:\n",i);
		scanf(" %c", &g->vertex[i]);//这里%c前面加上空格,来屏蔽前面输入的空格,回车等,如果不加空格的话,可以在下面一行加上getchar()吃掉空格
		//getchar();
	}

	//初始化边为无穷大
	for (int i = 0; i < g->vertex_nums; i++)
	{
		for (int j = 0; j < g->vertex_nums; j++)
		{
			g->edge[i][j] = INFINITY;
		}
	}

	//输入边的权值
	for (int k = 0; k < g->edge_nums; k++)
	{
		int i, j, w;
		printf("请输入边(Vi,Vj)的上下标i,j及其权值w:\n");
		scanf("%d,%d,%d", &i, &j, &w);
		g->edge[i][j] = w;
		g->edge[j][i] = w;	
	}

}


/*
int main(void)
{
	MGraph g;
	CreateMGraph(&g);
	return 0;
}
*/

 无向图的深度优先搜索DFS_邻接矩阵

//无向不带权图的深度优先搜索_邻接矩阵表示
//初始化:所有边的值为初始化为0,相邻的为1。

#include<stdio.h>
#include<stdlib.h>//INT_MAX在其中定义,这一行不能少

#define MAX_VERTEX 20//根据需要定义
#define INFINITY  INT_MAX

typedef int bool;
#define true 1
#define false 0

int visited[MAX_VERTEX];


typedef struct Graph
{
	char vertex[MAX_VERTEX];
	int edge[MAX_VERTEX][MAX_VERTEX];
	int vertex_nums, edge_nums;
}MGraph;


//创建图,键盘输入
void CreateMGraph(MGraph *g)
{
	printf("请输入要创建的图的顶点数和边数:\n");
	scanf("%d,%d", &g->vertex_nums, &g->edge_nums);
	for (int i = 0; i < g->vertex_nums; i++)
	{
		printf("请输入第%d顶点的值:\n", i);
		scanf(" %c", &g->vertex[i]);//这里%c前面加上空格,来屏蔽前面输入的空格,回车等,如果不加空格的话,可以在下面一行加上getchar()吃掉空格
									//getchar();
	}

	//初始化边为0
	for (int i = 0; i < g->vertex_nums; i++)
	{
		for (int j = 0; j < g->vertex_nums; j++)
		{
			g->edge[i][j] = 0;
		}
	}

	//输入边的权值
	for (int k = 0; k < g->edge_nums; k++)
	{
		int i, j, w;
		printf("请输入边(Vi,Vj)的上下标i,j及其权值w:\n");
		scanf("%d,%d,%d", &i, &j, &w);
		g->edge[i][j] = w;
		g->edge[j][i] = w;
	}

}

//创建图,当要输入的信息太多的时候,就这样创建图
void CreateMGraph1(MGraph *G)
{
	int i, j;

	G->edge_nums = 15;
	G->vertex_nums = 9;

	/* 读入顶点信息,建立顶点表 */
	G->vertex[0] = 'A';
	G->vertex[1] = 'B';
	G->vertex[2] = 'C';
	G->vertex[3] = 'D';
	G->vertex[4] = 'E';
	G->vertex[5] = 'F';
	G->vertex[6] = 'G';
	G->vertex[7] = 'H';
	G->vertex[8] = 'I';


	for (i = 0; i < G->vertex_nums; i++)/* 初始化图 */
	{
		for (j = 0; j < G->vertex_nums; j++)
		{
			G->edge[i][j] = 0;
		}
	}

	G->edge[0][1] = 1;
	G->edge[0][5] = 1;

	G->edge[1][2] = 1;
	G->edge[1][8] = 1;
	G->edge[1][6] = 1;

	G->edge[2][3] = 1;
	G->edge[2][8] = 1;

	G->edge[3][4] = 1;
	G->edge[3][7] = 1;
	G->edge[3][6] = 1;
	G->edge[3][8] = 1;

	G->edge[4][5] = 1;
	G->edge[4][7] = 1;

	G->edge[5][6] = 1;

	G->edge[6][7] = 1;


	for (i = 0; i < G->vertex_nums; i++)
	{
		for (j = i; j < G->vertex_nums; j++)
		{
			G->edge[j][i] = G->edge[i][j];
		}
	}

}

//深度优先搜索DFS算法,使用邻接矩阵实现
void DFS(MGraph *g, int i)
{
	printf("%c", g->vertex[i]);
	visited[i] = true;//表示顶点i已经访问了
	for (int j = 0; j < g->vertex_nums; j++)
	{
		if (g->edge[i][j] == 1 && !visited[j])
		{
			DFS(g, j);
		}
	}

}



void DFSTraverse(MGraph *g)
{
	for (int i = 0; i < g->vertex_nums; i++)
	{
		visited[i] = false;
	}
	for (int i = 0; i < g->vertex_nums; i++)
	{
		if (!visited[i])
			DFS(g, i);
	}
}

int main(void)
{
	MGraph g;
	CreateMGraph1(&g);
	DFSTraverse(&g);
	return 0;
}

 无向图的深度优先搜索DFS_邻接表

//无向图的深度优先搜索DFS_邻接表
#include<stdio.h>

#define MAX_VERTEX 20

typedef int bool;
#define true 1
#define false 0

int visited[MAX_VERTEX];

typedef struct EdgeNode
{
	int adjvex;
	struct EdgeNode * next;
}EdgeNode;

typedef struct VertexNode
{
	char data;
	int weitht;
	struct EdgeNode * firstEdge;
}VertexNode,AdjList[MAX_VERTEX];

typedef struct
{
	AdjList adjlist;
	int vertex_nums, edge_nums;
}GraphAdjList;

//创建图,从键盘输入
void CreateGraph(GraphAdjList *g)
{
	int i, j;
	printf("请输入顶点i,和边数j的值:\n");
	scanf("%d,%d", &g->vertex_nums, &g->edge_nums);
	for (i = 0; i < g->vertex_nums; i++)//建立顶点表
	{
		printf("清输入第%d个顶点Vi的值:\n",i);
		scanf(" %c", &g->adjlist[i].data);
		g->adjlist[i].firstEdge = NULL;//将边表置为空表,这一行不能删,删了边表就没有结尾了,尾指针要为NULL。

	}
	for (int k = 0; k < g->edge_nums; k++)//建立边表
	{
		printf("请输入要添加的第%d条边i,j值:\n",k);
		scanf("%d,%d", &i, &j);
		EdgeNode *e = (EdgeNode*)malloc(sizeof(EdgeNode));
		e->adjvex = j;
		e->next = g->adjlist[i].firstEdge;
		g->adjlist[i].firstEdge = e;

		e = (EdgeNode*)malloc(sizeof(EdgeNode));
		e->adjvex = i;
		e->next = g->adjlist[j].firstEdge;
		g->adjlist[j].firstEdge = e;
	}
}

//每回都从键盘输入累死个人,直接创建图。
void CreateGraph1(GraphAdjList *g)
{
	g->vertex_nums = 9;
	g->edge_nums = 15;
	for (int i = 0; i < g->vertex_nums; i++)//给顶点赋值
	{
		g->adjlist[i].data = 'A' + i;
		g->adjlist[i].firstEdge = NULL;//这一行别遗漏
	}
	int a[15] = { 0,0,1,1,1,2,2,3,3,3,3,4,4,5,6 };//把要创建的边的顶点存储起来
	int b[15] = { 1,5,2,6,8,3,8,4,6,7,8,5,7,6,7 };//上下对应构成边

	for (int k = 0; k < g->edge_nums; k++)//建立边表
	{
		

		EdgeNode *e = (EdgeNode*)malloc(sizeof(EdgeNode));
		e->adjvex = b[k];
		e->next = g->adjlist[a[k]].firstEdge;
		g->adjlist[a[k]].firstEdge = e;

		e = (EdgeNode*)malloc(sizeof(EdgeNode));
		e->adjvex = a[k];
		e->next = g->adjlist[b[k]].firstEdge;
		g->adjlist[b[k]].firstEdge = e;
	}
}

void DFS(GraphAdjList *g, int i)
{
	visited[i] = true;
	printf("%c", g->adjlist[i].data);
	EdgeNode* p = g->adjlist[i].firstEdge;
	while (p)
	{
		if (!visited[p->adjvex])
		{
			DFS(g, p->adjvex);
		}
		p = p->next;
	}

}

void DFSTraverse(GraphAdjList *g)
{
	for (int i = 0; i < g->vertex_nums; i++) 
	{
		visited[i] = false;
	}
	for (int i = 0; i < g->vertex_nums; i++)
	{
		if (!visited[i])
		{
			DFS(g, i);
		}
	}
}


int main()
{
	GraphAdjList g;
	CreateGraph1(&g);
	DFSTraverse(&g);
}

无向图的广度优先搜索BFS_邻接矩阵

//无向图的广度优先搜索BFS,需要用到队列。


#include<stdio.h>
#include<stdlib.h>//INT_MAX在其中定义,这一行不能少

#define MAX_VERTEX 20//根据需要定义图的顶点最大数
#define INFINITY  INT_MAX

typedef int bool;
#define true 1
#define false 0

int visited[MAX_VERTEX];


typedef struct Graph
{
	char vertex[MAX_VERTEX];
	int edge[MAX_VERTEX][MAX_VERTEX];
	int vertex_nums, edge_nums;
}MGraph;

//使用顺序存储结构实现循环队列
typedef struct SequenceQueue
{
	int data[MAX_VERTEX];
	int front, rear;
}SqQueue;

//初始化循环队列
void InitQueue(SqQueue *q)
{
	q->rear = q->front = 0;
}

//判断队列是否为空
bool QueueEmpty(SqQueue *q)
{
	if (q->front == q->rear)
		return true;
	else
		return false;
}

//入队
bool EnQueue(SqQueue *q,int val)
{
	if ((q->rear + 1) % MAX_VERTEX == q->front)
	{
		return false;
	}
	q->data[q->rear] = val;
	q->rear=(q->rear+1)%MAX_VERTEX;
	return true;
}

//出队
bool DeQueue(SqQueue *q, int *val)
{
	if (q->rear == q->front)
	{
		return false;
	}
	*val = q->data[q->front];
	q->front = (q->front+1)%MAX_VERTEX;
	return true;
}

//创建图,键盘输入
void CreateMGraph(MGraph *g)
{
	printf("请输入要创建的图的顶点数和边数:\n");
	scanf("%d,%d", &g->vertex_nums, &g->edge_nums);
	for (int i = 0; i < g->vertex_nums; i++)
	{
		printf("请输入第%d顶点的值:\n", i);
		scanf(" %c", &g->vertex[i]);//这里%c前面加上空格,来屏蔽前面输入的空格,回车等,如果不加空格的话,可以在下面一行加上getchar()吃掉空格
									//getchar();
	}

	//初始化边为0
	for (int i = 0; i < g->vertex_nums; i++)
	{
		for (int j = 0; j < g->vertex_nums; j++)
		{
			g->edge[i][j] = 0;
		}
	}

	//输入边的权值
	for (int k = 0; k < g->edge_nums; k++)
	{
		int i, j, w;
		printf("请输入边(Vi,Vj)的上下标i,j及其权值w:\n");
		scanf("%d,%d,%d", &i, &j, &w);
		g->edge[i][j] = w;
		g->edge[j][i] = w;
	}

}

//创建图,当要输入的信息太多的时候,就这样创建图
void CreateMGraph1(MGraph *G)
{
	int i, j;

	G->edge_nums = 15;
	G->vertex_nums = 9;

	/* 读入顶点信息,建立顶点表 */
	G->vertex[0] = 'A';
	G->vertex[1] = 'B';
	G->vertex[2] = 'C';
	G->vertex[3] = 'D';
	G->vertex[4] = 'E';
	G->vertex[5] = 'F';
	G->vertex[6] = 'G';
	G->vertex[7] = 'H';
	G->vertex[8] = 'I';


	for (i = 0; i < G->vertex_nums; i++)/* 初始化图 */
	{
		for (j = 0; j < G->vertex_nums; j++)
		{
			G->edge[i][j] = 0;
		}
	}

	G->edge[0][1] = 1;
	//G->edge[0][5] = 1;

	G->edge[1][2] = 1;
	G->edge[1][8] = 1;
	//G->edge[1][6] = 1;

	//G->edge[2][3] = 1;
	G->edge[2][8] = 1;

	G->edge[3][4] = 1;
	G->edge[3][7] = 1;
	G->edge[3][6] = 1;
	//G->edge[3][8] = 1;

	G->edge[4][5] = 1;
	G->edge[4][7] = 1;

	G->edge[5][6] = 1;

	G->edge[6][7] = 1;


	for (i = 0; i < G->vertex_nums; i++)
	{
		for (j = i; j < G->vertex_nums; j++)
		{
			G->edge[j][i] = G->edge[i][j];
		}
	}

}

//广度优先遍历
void BFSTraverse(MGraph *g)
{
	int i;
	for (i = 0; i < g->vertex_nums; i++)
	{
		visited[i] = false;
	}
	SqQueue q;
	InitQueue(&q);
	for (i = 0; i < g->vertex_nums; i++)
	{
		int temp = i;//这里记得保存i的值,不然图不连通时,会有问题。
		if (!visited[i])
		{
			visited[i] = true;
			printf("%c", g->vertex[i]);
			EnQueue(&q, i);
		}
		while (!QueueEmpty(&q))
		{
			DeQueue(&q, &i);
			for (int j = 0; j < g->vertex_nums; j++)
			{
				if (g->edge[i][j] == 1 && !visited[j])
				{
					visited[j] = true;
					printf("%c", g->vertex[j]);
					EnQueue(&q, j);
				}
			}
		}
		i = temp;
	}
	
}



int main(void)
{
	MGraph g;
	CreateMGraph1(&g);
	BFSTraverse(&g);
	return 0;
}

无向图的广度优先搜索BFS_邻接表

//无向图的深度优先搜索DFS_邻接表
#include<stdio.h>

#define MAX_VERTEX 20

typedef int bool;
#define true 1
#define false 0

int visited[MAX_VERTEX];

typedef struct EdgeNode
{
	int adjvex;
	struct EdgeNode * next;
}EdgeNode;

typedef struct VertexNode
{
	char data;
	int weitht;
	struct EdgeNode * firstEdge;
}VertexNode, AdjList[MAX_VERTEX];

typedef struct
{
	AdjList adjlist;
	int vertex_nums, edge_nums;
}GraphAdjList;

//使用顺序存储结构实现循环队列
typedef struct SequenceQueue
{
	int data[MAX_VERTEX];
	int front, rear;
}SqQueue;

//初始化循环队列
void InitQueue(SqQueue *q)
{
	q->rear = q->front = 0;
}

//判断队列是否为空
bool QueueEmpty(SqQueue *q)
{
	if (q->front == q->rear)
		return true;
	else
		return false;
}

//入队
bool EnQueue(SqQueue *q, int val)
{
	if ((q->rear + 1) % MAX_VERTEX == q->front)
	{
		return false;
	}
	q->data[q->rear] = val;
	q->rear = (q->rear + 1) % MAX_VERTEX;
	return true;
}

//出队
bool DeQueue(SqQueue *q, int *val)
{
	if (q->rear == q->front)
	{
		return false;
	}
	*val = q->data[q->front];
	q->front = (q->front + 1) % MAX_VERTEX;
	return true;
}

//创建图,从键盘输入
void CreateGraph(GraphAdjList *g)
{
	int i, j;
	printf("请输入顶点i,和边数j的值:\n");
	scanf("%d,%d", &g->vertex_nums, &g->edge_nums);
	for (i = 0; i < g->vertex_nums; i++)//建立顶点表
	{
		printf("清输入第%d个顶点Vi的值:\n", i);
		scanf(" %c", &g->adjlist[i].data);
		g->adjlist[i].firstEdge = NULL;//将边表置为空表,这一行不能删,删了边表就没有结尾了,尾指针要为NULL。

	}
	for (int k = 0; k < g->edge_nums; k++)//建立边表
	{
		printf("请输入要添加的第%d条边i,j值:\n", k);
		scanf("%d,%d", &i, &j);
		EdgeNode *e = (EdgeNode*)malloc(sizeof(EdgeNode));
		e->adjvex = j;
		e->next = g->adjlist[i].firstEdge;
		g->adjlist[i].firstEdge = e;

		e = (EdgeNode*)malloc(sizeof(EdgeNode));
		e->adjvex = i;
		e->next = g->adjlist[j].firstEdge;
		g->adjlist[j].firstEdge = e;
	}
}

//每回都从键盘输入累死个人,直接创建图。
void CreateGraph1(GraphAdjList *g)
{
	g->vertex_nums = 9;
	g->edge_nums = 11;
	for (int i = 0; i < g->vertex_nums; i++)//给顶点赋值
	{
		g->adjlist[i].data = 'A' + i;
		g->adjlist[i].firstEdge = NULL;//这一行别遗漏
	}
	//int a[15] = { 0,0,1,1,1,2,2,3,3,3,3,4,4,5,6 };//把要创建的边的顶点存储起来
	//int b[15] = { 1,5,2,6,8,3,8,4,6,7,8,5,7,6,7 };//上下对应构成边

	int a[11] = { 0,1,1,2,3,3,3,4,4,5,6 };//把要创建的边的顶点存储起来
	int b[11] = { 1,8,2,8,4,6,7,5,7,6,7 };//上下对应构成边

	for (int k = 0; k < g->edge_nums; k++)//建立边表
	{


		EdgeNode *e = (EdgeNode*)malloc(sizeof(EdgeNode));
		e->adjvex = b[k];
		e->next = g->adjlist[a[k]].firstEdge;
		g->adjlist[a[k]].firstEdge = e;

		e = (EdgeNode*)malloc(sizeof(EdgeNode));
		e->adjvex = a[k];
		e->next = g->adjlist[b[k]].firstEdge;
		g->adjlist[b[k]].firstEdge = e;
	}
}


void BFSTraverse(GraphAdjList *g)
{
	int i;
	for (i = 0; i < g->vertex_nums; i++)
	{
		visited[i] = false;
	}
	SqQueue q;
	InitQueue(&q);
	for(i=0;i<g->vertex_nums;i++)
	{ 
		int temp = i;//这里还是加上这个,不要改变i的值。
		if (!visited[i])
		{
			visited[i] = true;
			printf("%c", g->adjlist[i].data);
			EnQueue(&q, i);
		}
		while (!QueueEmpty(&q))
		{
			DeQueue(&q, &i);
			EdgeNode *p = g->adjlist[i].firstEdge;
			/*while (p && !visited[p->adjvex])//这样写有问题,正确写法是下面的
			{
				visited[p->adjvex] = true;
				printf("%c", g->adjlist[p->adjvex].data);
				EnQueue(&q, p->adjvex);
				p = p->next;
			}*/
			while (p)
			{
				if (!visited[p->adjvex])
				{
					visited[p->adjvex] = true;
					printf("%c", g->adjlist[p->adjvex].data);
					EnQueue(&q, p->adjvex);
				}
				p = p->next;
			}
		}
		i = temp;
	}
}



int main()
{
	GraphAdjList g;
	CreateGraph1(&g);
	BFSTraverse(&g);
}

prim

//prim算法,邻接矩阵表示
#include<stdio.h>
#include<stdlib.h>

#define MAX_VERTEX 9
#define INFINITY INT_MAX

typedef struct Graph
{
	char vertex[MAX_VERTEX];
	int edge[MAX_VERTEX][MAX_VERTEX];
	int vertex_nums, edge_nums;
}MGraph;


void CreateMGraph(MGraph *g)
{
	g->vertex_nums = 9;
	g->edge_nums = 15;
	//顶点赋值
	for (int i = 0; i < 9; i++)
	{
		g->vertex[i] = 'A' + i;
	}

	for (int i = 0; i < g->vertex_nums; i++)
	{
		for (int j = 0; j < g->vertex_nums; j++)
		{
			if (i == j)
				g->edge[i][j] = 0;
			else
				g->edge[i][j] = INFINITY;
		}
	}

	g->edge[0][1] = 10;
	g->edge[0][5] = 11;
	g->edge[1][2] = 18;
	g->edge[1][6] = 16;
	g->edge[1][8] = 12;
	g->edge[2][3] = 22;
	g->edge[2][8] = 8;
	g->edge[3][4] = 20;
	g->edge[3][6] = 24;
	g->edge[3][7] = 16; 
	g->edge[3][8] = 21;
	g->edge[4][5] = 26;
	g->edge[4][7] = 7;
	g->edge[5][6] = 17;
	g->edge[6][7] = 19;

	for (int i = 0; i < g->vertex_nums; i++)
	{
		for (int j = 0; j < g->vertex_nums; j++)
		{
			g->edge[j][i] = g->edge[i][j];//注意,这里不要写反了g->edge[i][j]=g->edge[j][i]
		}
	}

}


void MinSpanTree_Prim(MGraph *g)
{
	int adjvex[MAX_VERTEX];//保存相关顶点下标,
	int lowcost[MAX_VERTEX];//保存相关顶点间边的权值
	adjvex[0] = 0;
	lowcost[0] = 0;//第一个顶点加入生成树,
	for (int i = 1; i < g->vertex_nums; i++)
	{
		adjvex[i] = 0;//初始化都为v0顶点的下标
		lowcost[i] = g->edge[0][i];//将v0顶点与之前有边的权值存入数组
	}
	for (int i = 1; i < g->vertex_nums; i++)
	{
		int min = INFINITY;//初始化最小权为无穷大
		int k;
		for (int j = 1; j < g->vertex_nums; j++)
		{
			if (lowcost[j]&&min > lowcost[j])
			{
				min = lowcost[j];
				k = j;
			}
		}
		lowcost[k] = 0;//将顶点k加入最小生成树
		printf("(%d,%d)\n", adjvex[k], k);//打印边
		for (int j = 1; j < g->vertex_nums; j++)
		{
			if (lowcost[j] && g->edge[k][j] < lowcost[j])//再比较其他顶掉到k的距离
			{
				lowcost[j] = g->edge[j][k];//将较小权值存入lowcost
				adjvex[j] = k;//将k存入adjvex
			}
		}

	}
}


int main(void)
{
	MGraph g;
	CreateMGraph(&g);
	MinSpanTree_Prim(&g);
	return 0;
}

kruskal算法

//最小生成数K算法
#include<stdio.h>
#include<stdlib.h>

#define INFINITY INT_MAX
#define MAX_VERTEX 9
#define MAX_EDGE 15
typedef struct
{
	int vertex[MAX_VERTEX];
	int edge[MAX_VERTEX][MAX_VERTEX];
	int vertex_nums, edge_nums;
}MGraph;


//定义K算法中边的数据结构,包括起点,终点,权重
typedef struct
{
	int start, end, weight;
}Edge;

void CreateMGraph(MGraph *g)
{
	g->vertex_nums = 9;
	g->edge_nums = 15;
	//顶点初始化
	for (int i = 0; i < g->vertex_nums; i++)
	{
		g->vertex[i] = 'A' + i;
	}

	//边初始化
	for (int i = 0; i < g->vertex_nums; i++)
	{
		for (int j = 0; j < g->vertex_nums; j++)
		{
			if (i == j)
				g->edge[i][j] = 0;
			else
				g->edge[i][j] = INFINITY;
		}
	}

	//输入边值
	g->edge[0][1] = 10;
	g->edge[0][5] = 11;
	g->edge[1][2] = 18;
	g->edge[1][6] = 16;
	g->edge[1][8] = 12;
	g->edge[2][3] = 22;
	g->edge[2][8] = 8;
	g->edge[3][4] = 20;
	g->edge[3][6] = 24;
	g->edge[3][7] = 16;
	g->edge[3][8] = 21;
	g->edge[4][5] = 26;
	g->edge[4][7] = 7;
	g->edge[5][6] = 17;
	g->edge[6][7] = 19;

	//边的对称性
	for (int i = 0; i < g->vertex_nums; i++)
	{
		for (int j = 0; j < g->vertex_nums; j++)
		{
			g->edge[j][i] = g->edge[i][j];//注意这里不要写反了
		}
	}
}

//交换e[j]和e[j+1]中对应的start,end,weight的值
void Swap(Edge *e, int j)
{
	int temp = e[j].start;
	e[j].start = e[j + 1].start;
	e[j + 1].start = temp;

	temp = e[j].end;
	e[j].end = e[j + 1].end;
	e[j + 1].end = temp;

	temp = e[j].weight;
	e[j].weight = e[j + 1].weight;
	e[j + 1].weight = temp;

}

//从邻接矩阵创建边集合
void GenerateEdge(MGraph *g,Edge *e)
{
	int num = 0;//表示边集中的第num条边
	//给边集数组赋值
	for (int i = 0; i < g->vertex_nums-1; i++)
	{
		for (int j = i + 1; j < g->vertex_nums; j++)
		{
			if (g->edge[i][j] < INFINITY)
			{
				e[num].start = i;
				e[num].end = j;
				e[num].weight = g->edge[i][j];
				num++;
			}
		}
	}
	//编辑数组排序
	for (int i = 0; i < g->edge_nums-1; i++)
	{
		for (int j = 0; j < g->edge_nums - i-1; j++)
		{
			if (e[j].weight > e[j + 1].weight)
			{
				Swap(e,j);
			}
		}
	}
	printf("--------排序后的边集数组-------------------\n");
		for (int i = 0; i < 15; i++)
		{
			printf("%d %d %d\n", e[i].start, e[i].end, e[i].weight);
		}
}


//用于K算法
int Find(int *father, int i)
{
	while (father[i])
	{
		i = father[i];
	}
	return i;
}

void Kruskal(MGraph *g,Edge *e)
{
	int father[MAX_VERTEX] = { 0 };
	for (int i = 0; i < g->edge_nums; i++)
	{
		int m = Find(father, e[i].start);
		int n = Find(father, e[i].end);
		if (m != n)/* 假如n与m不等,说明此边没有与现有的生成树形成环路 */
		{
			father[m] = n;/* 将此边的结尾顶点放入下标为起点的parent中。 */
							/* 表示此顶点已经在生成树集合中 */
			printf("边(%d,%d)加入最小生成树,权值为%d\n", e[i].start, e[i].end, e[i].weight);
		}
	}
}

int main(void)
{
	MGraph g;
	Edge e[MAX_EDGE];
	CreateMGraph(&g);
	GenerateEdge(&g, e);
	
	Kruskal(&g, e);
	return 0;
}

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值