• 全部
  • 问答

一个c程序的奇怪问题,一直解决不了,请大家帮帮忙

woshigefantong 2011-11-14 03:55:55
我需要作的工作是这样的
给定一个图的文件,里面是这个样子
1,2表示1和2链接
2,3表示2和3相连
--
我每次从这个图中去掉一个degree(连接点最多的点),然后在剩下的点中寻找最大联通集团,比如在一个332个点的图中删掉118这个点,最大联通集团是329个点

我的代码如下,很长,写的有点乱。希望大家耐心看一下。程序是调试好的,可以运行的

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#define BUFLEN 1024
#define USER 332+1
#define LINENUM 2126

char *array[LINENUM];
long userOir[LINENUM][2];
long userDegree[USER];
long *userRelationUser[USER];
//下表从1开始,group[0]=0没有意义
long group[USER];

long grouptmp[USER];
long groupresult[USER];
long groupcount=0;
long groupcounttmp=0;

void copygroup(long grouptmp[USER],long groupresult[USER]){
long i=0;
for(i=1;i<USER;i++){
groupresult[i]=grouptmp[i];
}
}

char filename[]="/home/zcj/project/c/LRNR/data/d/USAir_332_2126.txt";

void cleararray(long *group1,long count){
long i=0;
for(i=0;i<USER;i++){
group1[i]=-1;
}
}

void copyarray(long group[USER]){
}
/**
在申请好的user和item的链表中填写关系
**/
void createRelationForUserAndItem(long *userRelationUser[USER],long userOir[LINENUM][2]){
//从userItem[LINENUM][2]中提取关系
long userid1=0;
long userid2=0;
long i=0;
for(i=0;i<LINENUM;i++){


userid1=userOir[i][0];
userid2=userOir[i][1];
userRelationUser[userid1][0]++;
userRelationUser[userid1][userRelationUser[userid1][0]]=userid2;

userRelationUser[userid2][0]++;
userRelationUser[userid2][userRelationUser[userid2][0]]=userid1;

}
}


/**
为*t申请一个n长度的数组空间
**/
long *mal(long *t,long n){

long i=0;
t=(long*)malloc(sizeof(long)*n);
if(NULL==t){
printf("内存申请失败");
}
for(i=0;i<n;i++){
t[i]=0;
//printf("%d\n",t[i]);
}
return t;
}



void malForRelation(long *userRelationUser[USER],long userDegree[USER]){
long i=0;
for(i=0;i<USER;i++){
if(userDegree[i]==0){

userRelationUser[i]=mal(userRelationUser[i],1);
//userRelationItem[i][0]=0;

}else{

userRelationUser[i]=mal(userRelationUser[i],userDegree[i]+1);
}
}

}

readfileIntoCharArray(char *array[LINENUM],char *str){
FILE *file;
char buf[BUFLEN];
int len=0,i=0;
file=fopen(str,"r");
if(!file)return -1;
while(fgets(buf,BUFLEN,file))
{
len=strlen(buf);
array[i]=(char*)malloc(len+1);
if(!array[i])break;
if(len>3){
strcpy(array[i++],buf);
}
}
fclose(file);
}


void getUserDegree(long userOir[LINENUM][2]){
long user1=0;
long user2=0;
long i=0;
for(i=0;i<USER;i++){
userDegree[i]=0;
}
for(i=0;i<LINENUM;i++){
user1=userOir[i][0];
user2=userOir[i][1];
userDegree[user1]++;
userDegree[user2]++;
}

}

/**
字符串转化成数字
**/
long stringToNum(char *str){
//printf("传入的字符串=%s,",str);
long i=0,s=0;
while(*str!='\0'){
if (*str>='0' && *str<='9') // 把非数字的字符过滤掉
{
i=*str-'0';
s=s*10+i;
}
str++;
}
//printf("处理后的结果=%ld\n",s);
return s;
}

/**
把字符串根据sym作为分割副,分成两端,再分别转化成long,保存到long num[2]
**/
void slip(long num[2],char str[]){
int in=0;
char *p[20];
char *buf=str;
while((p[in]=strtok(buf,","))!=NULL) {
buf=p[in];
in++;
buf=NULL; }

num[0]=stringToNum(p[0]);
num[1]=stringToNum(p[1]);



}
//获得当前最大degree的userid
long getMaxDegreeId(long group1[USER],long userDegree[USER]){
long i=0;
long max=0;
long maxi=0;
for(i=1;i<USER;i++){
if(group1[i]==-1){
continue;
}
if(userDegree[group1[i]]>max){
max=userDegree[group1[i]];
maxi=group1[i];
}
}
//printf("%ld,%ld\n",maxi,max);
return maxi;
}

void filluserItemOir(long userItemOir[LINENUM][2]){
int i=0;
for(i=0;i<LINENUM;i++){
slip(userItemOir[i],array[i]);
}
}
//最初的联通集团,包括所有user
void initGroup(long group1[USER]){
long i=0;
for(i=1;i<USER;i++){
group1[i]=i;
}
}
//删除所有userdelete的关系
void deleteRelation(long userdelete){
long i=0;
long j=0;
long userid=0;
for(i=1;i<=userRelationUser[userdelete][0];i++){
userid=userRelationUser[userdelete][i];
if(userid==-1){
continue;
}
userRelationUser[userdelete][i]=-1;
//被删除关系的点的degree-1

userDegree[userid]--;

for(j=1;j<=userRelationUser[userid][0];j++){
if(userRelationUser[userid][j]==userdelete){

userRelationUser[userid][j]=-1;
break;
}
}

}
}
void getMaxGroupForPoint(long userid){
//这个点已经访问过了
if(grouptmp[userid]>0){
return;
}else{
grouptmp[userid]=userid;
groupcounttmp++;
}
long i=0;
long usertmp=0;
for(i=1;i<=userRelationUser[userid][0];i++){
usertmp=userRelationUser[userid][i];

if(usertmp>0){
getMaxGroupForPoint(usertmp);
}
}

}

void getMaxGroupForPoint2(long groupore[USER],long grouptmp[USER],long userid,long count){


//这个点已经访问过了

if(grouptmp[userid]!=-1){
return;
}

if(grouptmp[userid]==-1){

grouptmp[userid]=userid;

//groupcounttmp++;

}


long i=0;
long usertmp=0;

for(i=1;i<=userRelationUser[userid][0];i++){
usertmp=userRelationUser[userid][i];

if(groupore[usertmp]==-1||usertmp==-1){
continue;
}

getMaxGroupForPoint2(groupore,grouptmp,usertmp,count);


}




}





long getusercount(long group1[USER]){
long i=0;
long count=0;
for(i=1;i<USER;i++){
if(group1[i]>0){
count++;
}
}
return count;
}

void getMaxGroup(long group1[USER]){
long i=1;
long j=0;
//计算当前联通集团的点数
long userscount=getusercount(group1);


//获得当前联通集团中度最大的点
long userDelete=getMaxDegreeId(group1,userDegree);




if(userDegree[userDelete]==0){
return;
}

//delete this user
group1[userDelete]=-1;
userDegree[userDelete]=0;
//删除被删除点的所有关系,所有关联点的degree-1,
deleteRelation(userDelete);


long count=0;
groupcount=0;



for(i=1;i<USER;i++){




if(group1[i]>0){




//清空临时最大联通接团,grouptmp保存这当前的最大联通集团,删除点为-1,其他点为它的id
cleararray(grouptmp,USER);


//寻找当前点的最大联通集团
//getMaxGroupForPoint(i);


groupcounttmp=0;
getMaxGroupForPoint2(group1,grouptmp,i,userscount);
groupcounttmp=getusercount(grouptmp);



if(groupcounttmp>groupcount){
groupcount=groupcounttmp;
//保存当前计算的最大联通路径的结果到groupresult
copygroup(grouptmp,groupresult);
//如果当前最大联通数值已经大于去掉点之前联通值的1/2,就不需要计算了
if(groupcount>=userscount/2+1){

break;
}
}

}
}

printf("%ld,%ld\n",userDelete,groupcount);
getMaxGroup(groupresult);

}

int main(){
long i=0;
//group中保存最初的联通集团,也就是全部点。
initGroup(group);
readfileIntoCharArray(array,filename);
filluserItemOir(userOir);
getUserDegree(userOir);
malForRelation(userRelationUser,userDegree);
createRelationForUserAndItem(userRelationUser,userOir);
for(i=0;i<=userRelationUser[100][0];i++){

}


getMaxGroup(group);



}
我这个程序得到的结果是这样的
这个结果的意思是,这个图一共有332个点,118:329表示,删掉118这个点以后,最大联通集团有329个点。
118:329
261:314
255:311
152:304
182:296
230:289
166:287
67:281
112:277
201:270
147:269
144:268
162:266
293:262
176:261
258:257
248:253
47:251
217:250
221:246
299:245
146:242
174:238
65:230
177:226
219:223
109:222
179:221
311:220
8:11
26:3
1:2
2:1
实际上后来我用java程序验算,发现一直到311:220这个结果都是正确的,但是到了8:11这个结果就是错误的了。实际上在删掉8这个点以后,正确的联通集团个个数应该是182,可是不知道为什么,我的程序删到8这个点,就出错了。
在我的方法中,在getMaxGroup(long group1[USER])这个方法计算最大联通集团,这是个递归函数,每次递归,我都会在
group1中把已经不在最大联通集团的点的值变成-1,比如group1[1]=-1,表示当前最大联通集团中已经没有1这个点了,group1[100]=100表示,100这个点还在当前的最大联通集团上。
每次运行到删除8这个点的时候,总是发生一个非常奇怪的事情,递归程序刚进入的时候,group1里面有220个大于0的点(也就是有220个点在最大联通集团),我接下来会循环这个group1中每个大于0的点,用getMaxGroupForPoint2(group1,grouptmp,i,userscount),这个方法去查找当前的最大联通集团,可是奇怪的是,每次当最大联通集团为220的时候,运行完这个方法,本来有220个点的gourp1就变的只有11点了,这也是为什么出现8:11。我检查了很长时间也找不到问题在那里。这里限于文章篇幅,我没办法把我用于测试的数据集给你
如果那位有兴趣,可以给我发
email:zhangcj5@gmail.com,
我把我的数据集给你拿去测试。
我折腾这个搞了一个星期了。希望有人能够帮帮我,谢谢拉。





...全文
215 点赞 收藏 9
写回复
9 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
AnYidan 2011-11-14
分割,单步
回复
太长了
单步调试下
回复
lengxujun 2011-11-14
调试、调试、还是调试。
回复
AndyZhang 2011-11-14
你看看有没有什么特殊情况没有考虑
回复
yht8708 2011-11-14
太长了……
回复
心死 2011-11-14
看下GDB简单操作,太长了。
回复
HappyDelano 2011-11-14
[Quote=引用 7 楼 woshigefantong 的回复:]

我是ubunt下面,gcc编译
我不会单步调试---
[/Quote]gcc 编译的时候加上一个参数 -g ,然后就可以gdb调试了。gdb就几个命令,并且很简单也很有用,还是了解一下吧
回复
woshigefantong 2011-11-14
我是ubunt下面,gcc编译
我不会单步调试---
回复
相关推荐
发帖
C语言
创建于2007-09-28

6.3w+

社区成员

C语言相关问题讨论
申请成为版主
帖子事件
创建了帖子
2011-11-14 03:55
社区公告
暂无公告