C++中克鲁斯卡尔算法的运用
代码展示
#define MAX 5000
#include"stdio.h"
#include< stdlib.h >
#pragma warning(disable : 4996)
typedef struct
{
int fromvex; /*边的起始点*/
int endvex; /*边的终止点*/
int weight; /*边的权值*/
}g;
g tree[20] = { 0 }, GE[20] = { 0 }, TREE[20] = { 0 }, t;
int edge[20][20], s[20][20] = { 0 };
int n, m;
void kruskl()
{
int i, j, k, m1 = 0, m2 = 0, c;
printf("请输入顶点数和边数:");
scanf("%d%d", &n, &m);
for (i = 0; i < m; i++) /*输入图的所有边*/
{
printf("按起点,终点和权值依次输入:");
scanf("%d%d%d", &GE[i].fromvex, &GE[i].endvex, &GE[i].weight);
}
for (i = 1; i < m - 1; i++) /*按边的权值由小到大直接插入排序*/
{
t = GE[i];
j = i - 1;
while (j >= 0)
{
if (t.weight < GE[j].weight)
{
GE[j + 1] = GE[j];
j = j - 1;
}
else
break;
GE[j + 1] = t;
}
}
printf("\n排序后的边与对应的权值\n");
for (i = 0; i < m; i++) /*打印排序后的结果*/
printf("边:%d->%d权值:%d\n", GE[i].fromvex, GE[i].endvex, GE[i].weight);
for (i = 0; i < n; i++) /*初始化连通图*/
{
s[i][0] = 1; /*第0列表示一个连通分量中顶点数*/
s[i][1] = i; /*第1列后的列中均表示顶点的编号*/
}
j = 0; /*表示图G数组的序号*/
i = 0; /*表示树中边的序号*/
while (i < n - 1) /*找n-1条边形成最小生成树*/
{
k = 0; /*k表示s数组的行号*/
while (k < n) /*判断两个顶点为同一连通分量否*/
{
for (c = 1; c <= s[k][0]; c++) /*找所在的行号*/
{
if (GE[j].fromvex == s[k][c])
m1 = k; /*起点行号*/
if (GE[j].endvex == s[k][c])
m2 = k; /*终点行号*/
}
k++;
}
if (m1 != m2) /*不是同一连通分量将图中一条边合并到树中*/
{
TREE[i] = GE[j];
/*把图中的边放到树中*/
i = i + 1;
for (c = 1; c <= s[m2][0]; c++)
/*修改连通分量*/
{
s[m1][0] = s[m1][0] + 1;
/*顶点个数加1*/
s[m1][s[m1][0]] = s[m2][c];
/*终点编号合并*/
}
s[m2][0] = 0;
/*合并后顶点数为0*/
}
j++;
}
for (i = 0; i < n - 1; i++)
{
printf("生成树的起点,终点权值");
printf("%d\t->%d\t%d\n", TREE[i].fromvex, TREE[i].endvex, TREE[i].weight);
}
}
int main()
{
while (1)
{
int choice;
system("cls");
printf("顶点请用从零开始的连续整数表示,权值请小于100");
printf("\n\n\n");
printf(" *****>主菜单<*****\n\n\n");
printf(" 2----------克鲁斯卡尔算法\n");
printf(" 0----------退出程序\n");
printf("\n\n enter your choice :");
scanf("%d", &choice);
if (choice < 0 || choice>3)
return(0);
switch (choice)
{
case 2:
kruskl();
system("pause");
break;
case 0:
exit(0);
}
}
}
专心看人间!
浙公网安备 33010602011771号