最小生成树的数据结构实现

这里的最小生成树是指无向图的

每条边有大于0的整数的权值

这里有2种算法

一个为PRIM 这个算法时间要  O(n2)

另一个算法为Kruskal算法时间为O(elog2e)

但是这里还有个潜在的排序要实现,我这里排序并没有用好的算法

主要是为了实现Kruskal的思想

其排序的一些算法将在后续推出

#include <stdio.h>
#define MAX 100
#define INF 32767

void prim(int cost[][MAX],int ver,int  v)
{
    
int
 i,j,k;
    
int
 min;
    
int lowcost[MAX][2
];
    
for(i=0;i<ver;i++
)
    
{
        lowcost[i][
1]=v;   //这里是指这条边是由谁为起点的

        lowcost[i][0]=cost[v][i];        //这是这条边的权值
        if(i==v)
            lowcost[i][
1]=-1
;
    }

    
for(i=0;i<ver-1;i++)
    
{
        min
=
INF;

        
for(j=0;j<ver;j++
)
        
{
        
            
if(lowcost[j][1]!=-1&&lowcost[j][0]<min&&lowcost[j][0]!=0)  //寻找最小权值可用的边

            {
                min
=lowcost[j][0
];
                k
=
j;
            }

        }

        printf(
"%d---->%d cost %d ",lowcost[k][1],k,min);
        lowcost[k][
1]=-1
;
        
for(j=0;j<ver;j++)   //修改 lowcost 把新加进来的点的更短的边替换原来的边

        {
            
if(lowcost[j][1]!=-1&&(lowcost[j][0]>cost[k][j]&&cost[k][j]!=0||lowcost[j][0]==0
))
            
{
                lowcost[j][
0]=
cost[k][j];
                lowcost[j][
1]=
k;
            }

        }

    }

}


void Kruskal(int cost[][MAX],int ver,int  v)
{
    
int edge[MAX][3
];
    
int
 vset[MAX];
    
int
 i,j,k;
    
int
 a,b,c,t;
    
int
 min;
    
//这里用最简单的快排来 实际可以用更快的排序

    k=-1;
    
for(i=0;i<ver;i++
)
    
{
        vset[i]
=
i;
        
for(j=i;j<ver;j++
)
        
{
            
if(cost[i][j]!=0
)
            
{
                k
++
;
                edge[k][
0]=
i;
                edge[k][
1]=
j;
                edge[k][
2]=
cost[i][j];
            }

        }

    }

    
    
for(i=0;i<k;i++)
    
{
        min
=edge[i][2
];
        t
=
i;
        
for(j=i+1;j<k;j++
)
        
{
            
if(edge[j][2]<
min)
            
{
                t
=
j;
                min
=edge[j][2
];
            }

        }

        
if(t!=i)
        
{
            a
=edge[i][0];b=edge[i][1];c=edge[i][2
];
            edge[i][
0]=edge[t][0];edge[i][1]=edge[t][1];edge[i][2]=edge[t][2
];
            edge[t][
0]=a;edge[t][1]=b;edge[t][2]=
c;
        }

    }

   
// 到这里都是为了排序 其实可以用更好的方法来写 这里比较懒就将就下

    k
=1;
    i
=0
;
    
while(i<
ver)
    
{
        
if(vset[edge[i][0]]!=vset[edge[i][1]])   //vset为集合 这里不同的边选出来后会有不同的集合

        {
            printf(
"%d-->%d cost is %d ",edge[i][0],edge[i][1],edge[i][2
]);
            
for(j=0;j<ver;j++
)
                
if(vset[j]==vset[edge[i][1
]])
                    vset[j]
=vset[edge[i][0
]];        
            k
++
;
        }

        i
++;
    }

}


int  main()
{
    
int
 cost[MAX][MAX];
    
int
 i,j;
    
int
 a,b,c;
    
int
 ver,arc;
    
for(i=0;i<MAX;i++
)
        
for(j=0;j<MAX;j++
)
            cost[i][j]
=0
;
    printf(
"input the ver and arc "
);
    scanf(
"%d %d",&ver,&
arc);
    
for(i=0;i<arc;i++
)
    
{
        scanf(
"%d %d %d",&a,&b,&
c);
        cost[a][b]
=
c;
        cost[b][a]
=
c;
    }

    
for(i=0;i<ver;i++)
    
{
        
for(j=0;j<ver;j++
)
            printf(
"%d"
,cost[i][j]);
        printf(
" "
);
    }

    prim(cost,ver,
0);
    Kruskal(cost,ver,
0
);
    
return 0
;
}

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值