【问题标题】:C crash, BFS possible routes on large graphC崩溃,大图上的BFS可能路线
【发布时间】:2013-01-18 10:55:12
【问题描述】:

我用 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);
}

请注意,我使用的是结构图,它存储了我的图的所有边和节点,包括 nb_vertices(节点数)和距离矩阵 dist[i][j],它是与节点的距离i 到 j,如果未连接,则为 0。

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

【问题讨论】:

  • 在C语言中,你应该never cast the return value of malloc.
  • 另外,return 不是函数。我知道这种风格很常见,但我仍然认为值得指出的是,您这样做是有意识地(为了一些我不明白的好处)。

标签: c memory-management graph breadth-first-search


【解决方案1】:

您的dequeue 操作正在泄漏内存。你malloc 一些内存并将指针存储在nouveau 中,但是你说nouveau = old-&gt;suivant,丢失了malloc'd 缓冲区。从链表前面弹出时根本不需要malloc

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

至于为什么您没有收到“内存不足”错误,我猜您使用的是 Linux 并且您正在经历 overcommit 的悲惨影响。

【讨论】:

  • 感谢您的帮助!这可以让我的程序运行更长时间,但如果我在 50 个节点的图表上运行它,它仍然会在大约 30 秒后崩溃。
  • 另外,我在我的 Windows 分区上运行它。我可以尝试在 linux 端看看是否会改变...
  • @user1990100 另一个问题是您在struct queue 的定义中使用了int visited[n]。对于整个算法,您应该只需要一个访问集。
  • 实际上对于单个访问集,程序永远不会找到所有可能的路径,它只会找到子集。每条不同的路径都需要跟踪它经过的节点,而不知道它的邻居已经看到了哪些节点。
  • @user1990100:啊。但是,您需要将路径集作为父指针 DAG 保留在队列节点中(这很棘手,但可以通过引用计数来实现)。
猜你喜欢
  • 2021-06-15
  • 1970-01-01
  • 2020-09-07
  • 2017-05-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多