prim算法改进,C语言,用堆排序找到最小边开始,可读取文件

来源:互联网 发布:java 监听端口数据 编辑:程序博客网 时间:2024/05/22 15:39
1.不从节点1开始找,从图中最小的边开始找。其中求最小边用堆排序的算法

2.其余与yyprim类似;

3.将下面数据保存到1.txt


6 10 
1 2 10
1 4 30
1 5 45
2 3 50
2 5 50
2 6 25
3 5 35
3 6 15 
4 6 20 
5 6 55



#include <stdio.h>
#define INFINITY 0x7fffffff
#define MAX 100//最大顶点数
typedef int KeyType;
typedef char InfoType[10];


int arcs[MAX][MAX];
typedef struct{
KeyType key,k1,k2;//关键字项
InfoType data;//其他数据类型
}RecType;




void Sift(RecType R[],int s,int m){//调整堆,m为节点个数,s为父节点
int j;
RecType temp=R[s];
for(j=2*s;j<=m;j=2*j){
if(j<m&&R[j].key<R[j+1].key)j++;//若右孩子较大则把j指向右孩子
if(temp.key>R[j].key){//"<"得到结果为小根堆,首先输出的是最大的边,“>”得到的是大根堆,首先找到最小的边
R[s]=R[j];//将R[j]调整到双亲节点位置
s=j;//j的值赋给s,然后找树的下一个分支根节点
}
else break;
}
R[s]=temp;


}








int Prim(int arcs[][MAX],int n,int s,int m,int p){
//printf("最小边是:%d\n",s);
//printf("节点是:%d %d\n",m,p);
int i,j;
int sum=s;
int lowcost[MAX];//lowcost[i]记录以i为终点的边的最小权值,lowcost[i]=0,表示终点i加入生成树
int mst[MAX];//near[i]记录对应lowcost[i]的起点,near[i]=0表示i加入生成树










/*初始化节点,默认已选择1号节点加入生成树,从2号节点开始初始化*/
for(i=1;i<=n;i++){
if(arcs[i][m]<arcs[i][p]){
lowcost[i]=arcs[i][m];
mst[i]=m;//标记起点m
}
else{
lowcost[i]=arcs[i][p];
mst[i]=p;//标记起点p
}
}
mst[m]=0;//标记m号节点已经加入生成树
mst[p]=0;//标记n号节点已经加入生成树












/*找其余n-2条边*/
for(i=2;i<n;i++){
int min=INFINITY;
int minid=0;











/*找满足条件的最小权值的边以及节点*/
for(j=1;j<=n;j++){
if(lowcost[j]<min&&mst[j]!=0){
min=lowcost[j];//哪条边权值最小,赋给min
minid=j;//该权值最小的边的终点j赋给minid
}
}
/* 输出生成树边的信息:起点,终点,权值 */
printf("%d %d %d",mst[minid],minid,min);
printf("\n");
lowcost[minid]=0;//标记节点minid加入生成树
sum+=min;










/*更新当前节点minid到其他节点的权值*/
for(j=1;j<=n;j++){
if(arcs[minid][j]<lowcost[j]){//
lowcost[j]=arcs[minid][j];//更新权值信息
mst[j]=minid;//更新最小权值边的起点
}
}
}
return sum;


}
int main()
{

int i, j,k, m, n,p,q;
int minCOST;
RecType R[MAX];



FILE  *fp;
    
fp=fopen("1.txt", "r"); 
printf("图的节点数为:");
fscanf(fp, "%d", &p);        
    printf("%d", p);
printf("图的边数为:");
fscanf(fp, "%d", &q);        
    printf("%d", q);


    printf("\n"); 





for (i = 1; i <= p; i++)//节点数,构造二维数组
{
for (j = 1; j <= p; j++)
{
arcs[i][j] = INFINITY;
}
}


    //printf("输入读取的边数");
//scanf("%d",&n);
 
/* 读取边信息 */
for (i = 1; i <= q; i++)//边数
{
 fscanf(fp,"%d", &m);
 fscanf(fp,"%d", &n);
 fscanf(fp,"%d", &arcs[m][n]);
 arcs[n][m]=arcs[m][n];
 R[i].key=arcs[m][n];
 R[i].k1=m;
 R[i].k2=n;
 printf("%d %d %d\n", m,n,arcs[m][n]);
 //printf("%d\n",arcs[n][m]);
 
}
printf("\n");
printf("初始关键字");
for(k=1;k<=q;k++){
printf("%3d",R[k].key);
}
printf("\n");




/*循环建立初始堆*/
for(i=n/2;i>=1;i--)Sift(R,i,n);//循环建立初始堆,将其建为大根堆
printf("最小边是:%d\n",R[1].key);
printf("节点是:%d %d\n",R[1].k1,R[1].k2);
//printf("%d\n",arcs[1][2]);




minCOST=Prim(arcs,p,R[1].key,R[1].k1,R[1].k2);
printf("最小生成树的权值和为:%d",minCOST);




return 0;
}


0 0
原创粉丝点击