C崩溃,BFS可能路线在大图上

C崩溃,BFS可能路线在大图上,c,memory-management,graph,breadth-first-search,C,Memory Management,Graph,Breadth First Search,我用C编写了一个面包优先搜索算法,它搜索一个图结构(在本例中表示街道网格),并返回从节点a到节点B的所有可能路径 我发现,该函数对于小型图(大约24个节点)工作得非常快,但对于任何大于此值的图形都会崩溃。我认为malloc太多是个问题,所以我在函数中添加了free(),以便在运行队列时删除空间。不幸的是,这并不能解决问题。还请注意,我也从未收到“内存不足”的错误消息,因此我不确定发生了什么 void BFS_search(struct map *m, int start, int end){ i

我用C编写了一个面包优先搜索算法,它搜索一个图结构(在本例中表示街道网格),并返回从节点a到节点B的所有可能路径

我发现,该函数对于小型图(大约24个节点)工作得非常快,但对于任何大于此值的图形都会崩溃。我认为malloc太多是个问题,所以我在函数中添加了free(),以便在运行队列时删除空间。不幸的是,这并不能解决问题。还请注意,我也从未收到“内存不足”的错误消息,因此我不确定发生了什么

void BFS_search(struct map *m, int start, int end){
int n = m->nb_vertice+1;
int i=0;
int num=0;

//BFS requires a queue (pile) to maintain a list of nodes to visit 
struct queue {
    int current_node;
    int visited[n]; //cannot be a pointer! Otherwise the pointer may influence other queue structures
    struct queue *suivant;
};

//Function to add a node at the end of the queue.
void addqueue (int value, struct queue *old, int * old_seen) {
    int i;
    if (old->suivant==NULL){
        struct queue *nouveau;
        nouveau = (struct queue *)malloc(sizeof(struct queue));
        if (nouveau == NULL){
            printf("\n\nSnap! Out of memory, exiting...\n");
            exit(1);
        }
        nouveau->current_node = value;
        for (i = 0; i <= n; ++i){ 
            if (old_seen[i]==1)
                nouveau->visited[i]=1;
            else nouveau->visited[i]=0;
        }
        nouveau->suivant = NULL;
        old->suivant=nouveau;
        return;
    }
    else addqueue(value,old->suivant,old_seen);
}

struct queue * dequeue (struct queue *old){
    struct queue *nouveau;
    nouveau = (struct queue *)malloc(sizeof(struct queue));
    if (nouveau == NULL){
        printf("\n\nSnap! Out of memory, exiting...\n");
        exit(1);
    }
    nouveau = old->suivant;
    free(old);
    return(nouveau);
}

//the actual Breadth First Search Algorithm
int BFS(struct map *m, struct queue *q, int num, int end){
    int k;
    q->visited[q->current_node]=1; //mark current node as visited

    while(q!=NULL){
        //if we reached the destination, add +1 to the counter
        if (q->current_node==end){
            num+=1;
        }
        //if not the destination, look at adjacent nodes
        else {
            for (k=1;k<n;++k)
                if (m->dist[q->current_node][k]!=0 && q->visited[k]!=1){
                    addqueue(k,q,q->visited);
                }
            }
        //if queue is empty, stop and return the number 
        if (q->suivant==NULL){
            return(num);
        }
        //if queue is not empty, then move to next in queue
        else
            return(BFS(m,dequeue(q),num,end));
    }
}

//create and initialize start structure
struct queue *debut;
debut = (struct queue *)malloc(sizeof(struct queue));
for (i = 0; i <= n; ++i)
    debut->visited[i]=0;            
debut->current_node=start;
debut->visited[start]=1;
debut->suivant = NULL;

num=BFS(m,debut,0,end);
printf("\nIl existe %d routes possibles! \n",num);
}
void BFS\u搜索(结构映射*m,int开始,int结束){
int n=m->nb\u垂直+1;
int i=0;
int num=0;
//BFS需要一个队列(堆)来维护要访问的节点列表
结构队列{
int当前_节点;
int visted[n];//不能是指针!否则指针可能会影响其他队列结构
结构队列*suivant;
};
//函数在队列末尾添加一个节点。
void addqueue(int值,结构队列*旧,int*旧){
int i;
如果(旧->suivant==NULL){
结构队列*nouveau;
nouveau=(结构队列*)malloc(sizeof(结构队列));
if(nouveau==NULL){
printf(“\n\n快照!内存不足,正在退出…\n”);
出口(1);
}
nouveau->current_node=值;
对于(i=0;我访问了[i]=1;
else nouveau->visited[i]=0;
}
nouveau->suivant=NULL;
旧->苏万特=新潮;
返回;
}
else addqueue(value,old->suivant,old_-seen);
}
结构队列*出列(结构队列*旧){
结构队列*nouveau;
nouveau=(结构队列*)malloc(sizeof(结构队列));
if(nouveau==NULL){
printf(“\n\n快照!内存不足,正在退出…\n”);
出口(1);
}
新的=旧的->新的;
免费(旧);
回归(新潮);
}
//实际的广度优先搜索算法
intBFS(结构映射*m,结构队列*q,intnum,intend){
int k;
q->已访问[q->当前_节点]=1;//将当前节点标记为已访问
while(q!=NULL){
//如果我们到达目的地,在计数器上加+1
if(q->current_node==end){
num+=1;
}
//如果不是目的地,请查看相邻节点
否则{
对于(k=1;kdist[q->current_node][k]!=0&&q->visted[k]!=1){
addqueue(k,q,q->已访问);
}
}
//如果队列为空,请停止并返回号码
如果(q->suivant==NULL){
返回(num);
}
//若队列不为空,则移动到队列中的下一个
其他的
返回(BFS(m,出列(q),num,end));
}
}
//创建并初始化启动结构
结构队列*首次登场;
首秀=(结构队列*)malloc(sizeof(结构队列));
对于(i=0;我访问了[i]=0;
首次登场->当前_节点=开始;
首次登场->访问[开始]=1;
首次登场->suivant=NULL;
num=BFS(m,首次出现,0,结束);
printf(“\nIl存在%d条可能的路由!\n”,num);
}
请注意,我使用的是一个结构映射,它存储图形的所有边和节点,包括nb_顶点(节点数)和距离矩阵dist[I][j],它是从节点I到j的距离,如果未连接,则为0


任何帮助都将不胜感激!我认为这是可用内存量的错误。如果我无法避免内存问题,我至少希望有一种方法来输出特定的错误消息…

您的
出列
操作正在泄漏内存。您
malloc
一些内存,并将指针存储在
nouveau
,然后你说
nouveau=old->suivant
,失去了
malloc
'd缓冲区。从链接列表前面弹出时,根本不需要
malloc

struct queue *dequeue(struct queue *q)
{
    struct queue *next = q->suivant;
    free(q);
    return next;
}

至于为什么你没有出现“内存不足”错误,我猜你是在Linux上,并且你正在经历这种错误带来的悲惨后果。

在C语言中,你也应该,
return
不是一个函数。我知道这种风格很常见,但我仍然认为值得指出,只是为了让你在知情的情况下这样做(为了一些我不理解的好处)。谢谢你的帮助!这允许我的程序运行更长一点,但如果我在50个节点的图形上运行它,大约30秒后它仍然会崩溃。另外,我正在Windows分区上运行它。我可以在linux端尝试看看这是否会改变情况…@user1990100另一个问题是您使用的
int-visted[n]
结构队列的定义中
。整个算法只需要一个访问集。实际上,使用一个访问集,程序永远不会找到所有可能的路径,它只会找到子集。每个不同的路径需要跟踪它所经过的节点,而不知道它的邻居是哪些节点已经看到了。@user1990100:Ah。但是,您需要将路径集作为父指针DAG保留在队列节点中(这很棘手,但在引用计数方面是可行的)。