MST最小生成树的Kruskal和Prim算法
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
1.实验目的(结出本次实验所涉及并要求掌握的知识点)
最小生成树kruskal算法和prim算法的实现
2.实验内容(结出实验内容具体描述)
最小生成树kruskal算法和prim算法的实现
3.算法描述及实验步骤(用适当的形式表达算法设计思想与算法实现步骤)
数据结构:
(MST也是图,所以实现用了邻接表表示)
void union_v(LinkGraph*g,int index,int j){
edgenode*p=g->adjlist[index].firstedge;
g->adjlist[index].state=j;
while(p){
if(g->adjlist[p->adjvex].state!=j)
union_v(g,p->adjvex,j);
p=p->next;
}
}
//(加边)对边按权排升序,每次考虑最小边,判断他两端是否是不同集合,是就把这边union
edges* Kruskal_MST(LinkGraph*g,int c){
edges*head=creatEdgeList(g);
edges*p;
edgenode*s;
int i,j;
//判断每一条边,是否需要union
printf("排序后的边结点:\n");
p=head->next;
while(p){
printf("%d %d %d",p->leftv,p->rightv,p->weigth);
printf("\n");
p=p->next;
}
p=head->next;
for(i=0;i<g->n;i++){
g->adjlist[i].state=i;// 初始化点集,每个点都位于不同的连通分量}
while(p){
if(g->adjlist[p->leftv].state!=g->adjlist[p->rightv].state){
// 只要这条边可以加入MST,就创建图结点
// 把这些边当成图结点,创建图(MST树)
p->flag=1;
i=p->leftv;
j=p->rightv;
s=(edgenode *)malloc(sizeof(edgenode));
s->adjvex=j;
s->weigth=p->weigth;
s->next=g->adjlist[i].firstedge; // 头插法创建邻接表
g->adjlist[i].firstedge=s;
if (c==0) { // c=0表示无向图
s=(edgenode *)malloc(sizeof(edgenode));
s->adjvex=i;
s->next=g->adjlist[j].firstedge;
g->adjlist[j].firstedge=s;
}
// union操作
int m=g->adjlist[i].state;
int n=g->adjlist[j].state;
if(m<n){
g->adjlist[j].state=m;
union_v(g,j,m);
}
else{
g->adjlist[i].state=n;
}
}
p=p->next;
}
// 返回边结点链表
return head;
}
Prim算法的实现:
edges* Prim_MST(LinkGraph*g,int c){
edges*head=creatEdgeList(g);
edges*p;
edgenode*s;
int i,j;
printf("排序后的边结点:\n");
p=head->next;
while(p){
printf("%d %d %d",p->leftv,p->rightv,p->weigth);
printf("\n");
p=p->next;
}
for(i=0;i<g->n;i++){
g->adjlist[i].state=0;// 初始化点集,所有点未在MST中}
//从head的第一条边的顶点出发,逐个寻找需要union的
int count=0;//用来记录目前MST中有多少个点
p=head->next;
g->adjlist[p->leftv].state=1;//选中第一个点加入
count++;int l,r;
while(count!=g->n){
p=head->next;
while(p){
l=g->adjlist[p->leftv].state;
r=g->adjlist[p->rightv].state;
// 只有l,r一个在点集,一个不在点集,才union
if(l+r == 1){
if(l*r==0){
p->flag=1;
count++;
// 建MST树/图
j=p->rightv;
s=(edgenode *)malloc(sizeof(edgenode));
s->adjvex=j;
s->weigth=p->weigth;
s->next=g->adjlist[i].firstedge; // 头插法创建邻接表
g->adjlist[i].firstedge=s;
if (c==0) { // c=0表示无向图
s=(edgenode *)malloc(sizeof(edgenode));
s->adjvex=i;
s->next=g->adjlist[j].firstedge;
g->adjlist[j].firstedge=s;
}
// union操作
if(l==0)
g->adjlist[p->leftv].state=1;
else if (r==0)
g->adjlist[p->rightv].state=1;
break;
}
else{
p=p->next;
}
}
else{
p=p->next;
}
}
}
// 返回边结点链表
return head;
}
4.调试过程及运行结果(详细记录在调试过程中出现的问题及解决方法。
记录实验执行的结果)
例1:
Kruskal算法实现:Prim算法实现
例2
Kruskal Prim
5. 总结(对实验结果进行分析,问题回答,实验心得体会及改进意见)
1.
对于两个算法,都存在着对边的排序(Prim每次选择最短的cross边)
所以设计了一个边edges的数据结构,存放两端结点,权重
2.
Kruskal算法是依次筛选每一条边(加边),修改连通分量。
对这个edges链表进行一次筛选,就可以得出MST;
Prim算法是依次(加点),然后重新检索edges链表,选择最短的跨边,把这个跨边的另一端点加入。
3.
因为两个算法构建MST时加边(加点)的顺序不一样,所以得到的邻接表可能不一样,相应的DFS遍历这课树(图)得到的序列也不一样
6.附录(程序源代码等)
见附件main.c。