我使用邻接矩阵图表示在C中实现了Kruskal算法,问题是,它不断弹出分段错误错误,我一直在试图找出错误很长一段时间而且我不能似乎找到了问题,还有其他人可以看一下吗? 感谢。
这是我的代码:
#include <stdio.h>
#include <stdlib.h>
#define MAXVERT 10
#define MAXEDGES 20
#define INF 100000
/*graph representation using an Adjacency matrix*/
typedef struct AdjMatrix
{
int nodes;
int adjMat[MAXVERT][MAXVERT];
} graph;
/*function prototypes*/
int find(int node, int *trees);
void merge(int i, int j, int *trees);
void printminimal(int min[][3], int n);
/*main algorithm*/
void kruskal(graph *g)
{
int EDGES[MAXEDGES][3]; /*graph edges*/
int MINEDGES[MAXVERT-1][3]; /*edges already in the minimal spanning tree*/
int nextedge=0;
int numedges=0;
int trees[MAXVERT]; /*tree subsets*/
int i, j, k;
int temp;
for(i=0;i<g->nodes;i++)
trees[i]=i;
k=0;
for(i=0; i<g->nodes; i++)
for(j=0; j<g->nodes; j++)
{
if(i<j)
{
EDGES[k][0]=i;
EDGES[k][1]=j;
EDGES[k][2]=g->adjMat[i][j];
k++;
}
else
break;
}
/*Bubblesort*/
for(i=0; i<g->nodes; i++)
for(j=0; j<i; j++)
{
if(EDGES[j][2] > EDGES[j+1][2])
{
temp=EDGES[j][0];
EDGES[j][0]=EDGES[j+1][0];
EDGES[j+1][0]=temp;
temp=EDGES[j][1];
EDGES[j][1]=EDGES[j+1][1];
EDGES[j+1][1]=temp;
temp=EDGES[j][2];
EDGES[j][2]=EDGES[j+1][2];
EDGES[j+1][2]=temp;
}
}
while(numedges < (g->nodes-1))
{
i=find(EDGES[nextedge][0], trees);
j=find(EDGES[nextedge][1], trees);
if((i!=j)&&(EDGES[nextedge][2]!=-1)) /*check if the nodes belong to the same subtree*/
{
merge(i,j,trees);
MINEDGES[numedges][0]=EDGES[nextedge][0];
MINEDGES[numedges][1]=EDGES[nextedge][1];
MINEDGES[numedges][2]=EDGES[nextedge][2];
numedges++;
}
nextedge++;
}
}
int find(int node, int *trees)
{
if(trees[node]!=node)
return trees[node];
else
return node;
}
void merge(int i, int j, int *trees)
{
if(i<j)
trees[j]=i;
else
trees[i]=j;
}
void printminimal(int min[][3], int n)
{
int i, weight=0;
printf("Minimal tree:\n(");
for(i=0;i<n;i++)
{
printf("(V%d,V%d), ", min[i][0],min[i][1]);
weight+=min[i][2];
}
printf(")\n Total weight sum of the minimal tree is: %d", weight);
}
int main(void)
{
int i,j;
graph *g=(graph *)malloc(sizeof(graph));
/*int adjMat[8][8] = {0,INF,INF,11,INF,1,7,
INF,0,INF,3,INF,4,8,INF,
INF,INF,0,INF,INF,INF,12,INF,
INF,3,INF,0,15,INF,INF,INF,
11,INF,INF,INF,0,20,INF,INF,
INF,4,INF,INF,20,0,INF,INF,
1,8,12,INF,INF,INF,0,5,
7,INF,INF,INF,INF,INF,5,0};*/
for(i=0;i<4;i++)
for(j=0;j<i;j++)
{
if(i==j)
{
g->adjMat[i][j]=0;
continue;
}
printf("%d-%d= ", i, j);
scanf("%d", &(g->adjMat[i][j]));
g->adjMat[j][i]=g->adjMat[i][j];
}
g->nodes=4;
kruskal(g);
}
答案 0 :(得分:2)
在kruskal
函数中,您打算填充EDGES
数组,不要:
for(i=0; i<g->nodes; i++)
for(j=0; j<g->nodes; j++)
{
if(i<j)
{
EDGES[k][0]=i;
EDGES[k][1]=j;
EDGES[k][2]=g->adjMat[i][j];
k++;
}
else
break;
}
对于j == 0
,i
永远不会< j
,因此您可以立即突破内循环。我怀疑它应该是i > j
。
由于EDGES
未初始化,find
会尝试访问未指定的trees
元素。
答案 1 :(得分:0)
我必须添加以下内容才能将其发送到kruskal
以使其从gcc编译:
int *dvra = trees;
然后,您可以使用调试信息对其进行编译:
gcc -g -o kruskal kruskal.c
并通过gdb运行:
gdb kruskal
然后您可以输入run
并输入以启动该程序。当提示输入值时,我输入了1,2,3,....
然后给出:
Program received signal SIGSEGV, Segmentation fault.
0x0000000000400a92 in find (node=32767, trees=0x7fffffffe110) at test.c:86
86 if(trees[node]!=node)
嗯,这很奇怪。树只保存10个项目(MAXVERT
定义的值),因此访问节点32767超出范围。如果在计算器程序中输入32767并进入编程(十六进制)模式,您会发现它是7FFF(或MAX_SHORT,最大16位有符号整数值)。这也很有趣。
注意:您可以使用print
命令(例如print node
)和使用bt
命令的回溯来调查变量值。
这些来自kruskal
中的while循环(唯一一个调用find
的地方),因此我们需要调查该值的来源。让我们退出gdb(按'q'然后输入然后用'y'确认并输入)。
将以下内容添加到while循环并运行生成的程序:
printf("%d: nextedge=%d EDGES[nextedge][0]=%d EDGES[nextedge][1]=%d\n", numedges, nextedge, EDGES[nextedge][0], EDGES[nextedge][1]);
给出:
0: nextedge=0 EDGES[nextedge][0]=-557487152 EDGES[nextedge][1]=32767
所以看起来EDGES[0]
没有被初始化,这指向了bubblesort上方的初始化循环中的if(i<j)
条件。好的,所以让我们通过在if循环中添加以下内容来跟踪初始化循环中发生的事情:
printf("EDGES[%d]: 0=%d 1=%d\n", k, i, j);
重新执行此操作,我们发现没有与此语句关联的行,因此它没有被执行。
将if条件更改为:
if(i<=j)
导致执行语句并且段错误消失。