Contents
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174

lowcost数组里的值是adjvex数组里的点指向相应下标的点的权值
lowcost数组保存相关顶点到邻接点(边)的权值,此权值是生成树里的点到该邻接点的最小权值
例如:
0 1 2 3 4 5 6
A B C D E F G
adjvex: 0 0 0 0 3 3 0
lowcost:0 7 x 0 15 6 x
lowcost[1]=7的意思是:0顶点(A)(adjvex[1])指向B点(相应下标)的权值
lowcost[4]=15的意思是:3顶点(D)(adjvex[4])指向E(相应下标)的权值

- prime算法是维护一个集合到某个点的最短距离的数组
- 迪杰斯特拉算法是维护一个点到点的最短距离的数组


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef char VertexType; //顶点类型应由用户定义
typedef int EdgeTyep; //边上的权值类型应由用户定义

#define MAXVEX 100 //最大顶点数,应由用户定义
#define INFINITY 65535 //用65535来代表无穷大
#define DEBUG

typedef struct Graph{
VertexType vexs[MAXVEX]; //顶点表
EdgeTyep arc[MAXVEX][MAXVEX]; //邻接矩阵,可看作边
int numVertexes, numEdges; //图中当前的顶点数和边数
}Graph;

//定位
int Locates(Graph *g, char ch)
{

int i;
for(i = 0; i < g->numVertexes; i++)
{
if(g->vexs[i] == ch)
break;
}
if(i >= g->numVertexes)
return -1;
return i;
}

//建立一个无向网图的邻接矩阵表示
void CreatGraph(Graph *g)
{

int i, j, w, k;
printf("please input numVertexes and numEdges\n");
scanf("%d %d", &(g->numVertexes), &(g->numEdges));
getchar();//下面要输入字符,所以要吃回车
#ifdef DEBUG//调试用
printf("%d %d\n", g->numVertexes, g->numEdges);
#endif
for(i = 0; i < g->numVertexes; i++)
{
printf("请输入顶点%d:\n", i);
scanf("%c", &(g->vexs[i]));
getchar();
/*g->vexs[i] = getchar();
while(g->vexs[i] == '\n')//吃回车
{
g->vexs[i] = getchar();
}*/

}
#ifdef DEBUG
for(i = 0; i < g->numVertexes; i++)
{
printf("%c ", g->vexs[i]);
}
printf("\n");
#endif
for(i = 0; i < g->numEdges; i++)
{
for(j = 0; j < g->numEdges; j++)
{
g->arc[i][j] = INFINITY; //邻接矩阵初始化
}
}
//getchar();//注意吃回车
for(k = 0; k < g->numEdges; k++)
{
char p, q;
printf("please input i, j, w in Edge(vi, vj)\n");

scanf("%c %c %d", &p, &q, &w);
getchar();//吃回车
int m = -1;
int n = -1;
m = Locates(g, p);
n = Locates(g, q);
if(n == -1 || m == -1)
{
printf("There is no vertex !\n");
return ;
}
g->arc[m][n] = w;
g->arc[n][m] = g->arc[m][n]; //因为是无向图,矩阵对称
}
}

//打印图
void printGraph(Graph g)
{

int i, j;
printf("The Graph is under this sentence\n");
for(i = 0; i < g.numVertexes; i++)
{
for(j = 0; j < g.numVertexes; j++)
{
printf("%5d ", g.arc[i][j]);
}
printf("\n");
}
}

//prime算法最小生成树
void MiniSpanTree_Prime(Graph g)
{

int mins, i, j, k;
int adjvex[MAXVEX]; //保存相关顶点下标
int lowcost[MAXVEX]; //保存相关顶点到邻接点(边)的权值,此权值是生成树里的点到该邻接点的最小权值
lowcost[0] = 0; //初始化第一个权值为0,即v0加入生成树
adjvex[0] = 0; //初始化第一个顶点下标为0
for(i = 1; i < g.numVertexes; i++)
{
//循环除下标为0外的全部顶点
lowcost[i] = g.arc[0][i]; //将v0顶点与之有边的权值存入数组
adjvex[i] = 0; //初始化都为v0下标
}
for(i = 1; i < g.numVertexes; i++)
{
mins = INFINITY; //初始化最小权值为无穷大
j = 1;
k = 0;
while(j < g.numVertexes) //循环全部顶点
{//如果权值不为0,且权值小于min
if(lowcost[j] != 0 && lowcost[j] < mins)
{
mins = lowcost[j]; //则让mins成为最小权值
k = j; //记录当前最小权值的下标
}
j++;
}
printf("(%d,%d)", adjvex[k], k);//打印当前顶点边中权值最小边//如果要建树就在这里加代码
lowcost[k] = 0; //将当前顶点的权值设置为0,表示此点为顶点且已经加入生成树

for(j = 1; j < g.numVertexes; j++)
{
if(lowcost[j] != 0 && g.arc[k][j] < lowcost[j])//如果k顶点到j顶点的边的权值小于现在lowcost数组中其他已记录的其他的点到j顶点的最小权值,则更新他
{
lowcost[j] = g.arc[k][j];
adjvex[j] = k;
}

}
}
printf("\n");
}


int main()
{

Graph g;
//邻接矩阵创建图
CreatGraph(&g);
//打印网图
printGraph(g);
//求最小生成树
MiniSpanTree_Prime(g);

return 0;
}
Contents