基于C语言的Kruskals算法
我有两个Kruskal算法实现。一个是我做的,另一个是我从朋友那里拿走的。这两个程序在我看来几乎一样,除了一些无关紧要的事情 他的程序给出的输出与我的不同,尽管我认为他们都给出了错误的边集,但权重正确 我的节目:基于C语言的Kruskals算法,c,algorithm,C,Algorithm,我有两个Kruskal算法实现。一个是我做的,另一个是我从朋友那里拿走的。这两个程序在我看来几乎一样,除了一些无关紧要的事情 他的程序给出的输出与我的不同,尽管我认为他们都给出了错误的边集,但权重正确 我的节目: #include<stdio.h> #include<stdlib.h> typedef struct info { int initial; int final; int weight; }info; void uon(int x,
#include<stdio.h>
#include<stdlib.h>
typedef struct info
{
int initial;
int final;
int weight;
}info;
void uon(int x,int y,int*p,int *r);
int findset(int x,int *p);
void sort(info *edgelist,int n);
void qksort(info *edgelist,int l,int u);
int partition(info *edgelist,int l,int u);
void makeset(int n,int *p,int *r);
int kruskal(info *edgelist,int n,int w);
int main()
{
FILE *fp;
int n,i,j,temp;
int **gmatrix,cost;
info *edgelist;
int cnt =0,a;
fp = fopen("grph.txt","r");
fscanf(fp,"%d",&n);
gmatrix=(int**)calloc(sizeof(int*),n);
for(i=0;i<n;i++)
gmatrix[i]=(int*)calloc(sizeof(int),n);
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
fscanf(fp,"%d",&temp);
gmatrix[i][j]=temp;
}
}
edgelist = (info*)calloc(sizeof(info),n*n);
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
printf("%d ",gmatrix[i][j]);
temp = gmatrix[i][j];
a=cnt;
if(temp !=0)
{
edgelist[a].initial = i;
edgelist[a].weight = temp;
edgelist[a].final = j;
cnt++;
}
}
printf("\n");
}
printf("%d \n",edgelist[0].initial);
printf("%d \n ",cnt);
cost =kruskal(edgelist,n,cnt);
printf("\nTotal Cost is %d",cost);
return 0;
}
int kruskal(info *edgelist,int n,int cnt)
{
int b,i,initial,dest,cost_cnt=0;
int *p,*r;
int cost=0;
info *krus;
p = (int*)calloc(sizeof(int),n);
r = (int*)calloc(sizeof(int),n);
makeset(n,p,r);
qksort(edgelist,0,cnt);
//sort(edgelist,w);
krus=(info*)calloc(sizeof(info),n-1);
for(i=0;i<cnt;i++)
{
//printf("INITIAL 1 : %d \n",edgelist[i].initial);
initial=findset(edgelist[i].initial,p);
// printf("INITIAL 2 : %d \n",initial);
dest=findset(edgelist[i].final,p);
if(initial!=dest)
{
b=cost_cnt;
krus[b].initial=initial;
krus[b].final=dest;
krus[b].weight=edgelist[i].weight;
cost_cnt++;
uon(initial,dest,p,r);
}
}
for(i=0;i<cost_cnt;i++)
{
printf("{%d,%d}: %d \n",krus[i].initial+1,krus[i].final+1, krus[i].weight);
cost = cost + krus[i].weight;
}
return cost;
}
void uon(int initial,int dest,int *p,int *r)
{
int u,v;
//link(findset(x),findset(y));
printf("\n X1 : %d",initial);
u = findset(initial,p);
printf("\n X2 : %d",initial);
v = findset(dest,p);
if(r[u]>r[v])
{
p[v] = u;
}
else
{
p[u] = v;
if(r[u]==r[v])
r[v] = r[v]+1;
}
}
int findset(int x,int *p)
{
if(x!=p[x])
{
p[x]=findset(p[x],p);
}
return p[x];
}
void makeset(int n,int *p,int *r)
{
int i;
for(i=0;i<n;i++)
{
p[i] = i;
r[i] = 0;
}
}
void qksort(info *edgelist,int l,int u) {
int pq;
if(l<u)
{
pq=partition(edgelist,l,u);
qksort(edgelist,l,pq-1);
qksort(edgelist,pq+1,u);
}
}
int partition(info *edgelist,int l,int u) {
int i,j,pq;
info pv,t;
pv.initial=edgelist[l].initial;
pv.final=edgelist[l].final;
pv.weight=edgelist[l].weight;
j=l;
for(i=l+1;i<=u;i++)
{
if(edgelist[i].weight<=pv.weight)
{
j++;
t=edgelist[i];
t.initial=edgelist[i].initial;
t.final=edgelist[i].final;
t.weight=edgelist[i].weight;
edgelist[i].initial=edgelist[j].initial;
edgelist[i].final=edgelist[j].final;
edgelist[i].weight=edgelist[j].weight;
edgelist[j].initial=t.initial;
edgelist[j].final=t.final;
edgelist[j].weight=t.weight;
}
}
pq=j;
t.initial=edgelist[pq].initial;
t.final=edgelist[pq].final;
t.weight=edgelist[pq].weight;
edgelist[pq].initial=edgelist[l].initial;
edgelist[pq].final=edgelist[l].final;
edgelist[pq].weight=edgelist[l].weight;
edgelist[l].initial=t.initial;
edgelist[l].final=t.final;
edgelist[l].weight=t.weight;
return(pq);
}
权重为37,但程序没有给出正确的边集。排序顺序
代码之间的区别在于,在快速分拣例行程序中,一个代码使用:
if(edgelist[i].weight<=pv.weight)
它在通过findset例程后存储初始变量和dest变量。这应替换为:
krus[b].initial=edgelist[i].initial
krus[b].final=edgelist[i].final
附笔。
顺便说一句,这两种解决方案都有调用的缺陷
qksort(edgelist,0,cnt);
而不是
qksort(edgelist,0,cnt-1);
但这对输出没有任何影响。(所发生的一切是,第一条显示的边看起来像是从0开始和结束,因此被忽略。)显然,打印的权重与节点编号不对应,因此如果解析和打印正常,则节点信息在某个地方损坏 快速排序实现似乎很好,修改节点信息的唯一其他地方是
kruskal()
函数
因此,提示:再次检查分配给
krus[b]。initial
。initial
真的是edgei
的初始节点号吗?这是您发布的大量代码,不太可能有很多用户会通读这些代码。到目前为止,您发现了哪些差异?哪些是重要的?哪些没有?这肯定是很多代码。引起我注意的一件事(可能不是唯一的问题,甚至不是主要问题)是calloc
的使用不一致:第一个参数应该是元素的数量,最后一个是元素的大小。这可能会影响内存的分配和清空方式。通常,这些错误的存在表明代码中还有其他不一致之处。Kruskals算法是一个众所周知的问题。我建议您找到一个已经实现的算法版本并使用它。你要求代码检查,这属于寻找一个更简单的输入图,也会导致你的问题。然后调试代码,看看哪里出错了。如果有必要,先在纸上做算法——或者使用。显然,至少有一件事“无关紧要”。。。谢谢你的回答。我反复查看了算法和程序,发现在为解图赋值时也在考虑同样的问题。这似乎不对。你在这里说的话证实了这一点。谢谢:)
krus[b].initial=initial;
krus[b].final=dest;
krus[b].initial=edgelist[i].initial
krus[b].final=edgelist[i].final
qksort(edgelist,0,cnt);
qksort(edgelist,0,cnt-1);