一、图的存储结构
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;
}