简体   繁体   English

C中使用队列和邻接表实现BFS

[英]Implementation of BFS using queue and adjacency list in C

I was solving a problem which allowed two types of operations: subtracting one from a number or multiplying it by two, with the source and the destination numbers provided.我正在解决一个允许两种类型操作的问题:从数字中减去一个或将其乘以 2,并提供源数字和目标数字。 Input constraints are 1<=n<=10^4 for both numbers.两个数字的输入约束为 1<=n<=10^4。 I'm supposed to output the number of operations needed to produce the desired number from the given one.我应该 output 从给定的操作数中产生所需的操作数。 The following is my implementation, getting runtime error and, obviously, I do not know why.以下是我的实现,出现运行时错误,显然,我不知道为什么。 It'll be awesome if someone explains the bug.如果有人解释这个错误,那就太棒了。 Thanks.谢谢。

#include <stdio.h>
#include <stdlib.h>
int g[22222][3], v[2222], size;//g == graph, v == visited and size == the size of queue
typedef struct _queue
{
    int val;
    struct _queue *next;
    struct _queue *prev;
} queue;
queue *head=NULL, *last=NULL;
void push(int val)
{
    queue *ptr=(queue *) malloc(sizeof(queue));
    ptr->next=NULL;
    ptr->val=val;
    if (head)
    {
        last->next=ptr;
        ptr->prev=last;
    }
    else
    {
        head=ptr;
        ptr->prev=NULL;
    }
    last=ptr;
}
void pop()
{
    if (size)
    {
        queue *ptr=last;
        last=last->prev;
        if (head) last->next=NULL;
        free(ptr);
    }
}
int front() {return last->val;}
int bfs(int s, int d)//s == source and d == destination
{
    int cnt=0;
    push(s);
    size++;
    v[s]=1;
    while (size)
    {
        int u=front();
        pop();
        size--;
        for (int j=1; j<=2; j++)
        {
            if (d==g[u][j]) return (cnt+1);
            if (!v[g[u][j]])
            {
                v[g[u][j]]=1;
                size++;
                push(g[u][j]);
            }
        }
        cnt++;
    }
}
int main()
{
    int n, m, val;
    scanf("%d%d", &n, &m);
    if (n==m) {printf("0"); return 0;}
    val=(n>m?n:m)*2;
    v[0]=1;
    for (int i=1; i<=val; i++)
    {
        g[i][1]=2*i;
        g[i][2]=i-1;
    }
    printf("%d", bfs(n, m));
    return 0;
}

You have implemented a stack ie LIFO (last in first out): you are adding to the end and retrieving from the end.您已经实现了一个堆栈,即 LIFO(后进先出):您正在添加到末尾并从末尾检索。

You should implement a queue ie FIFO (first in first out), so if you add to end, you should retrieve from front:你应该实现一个队列,即 FIFO(先进先出),所以如果你添加到 end,你应该从前面检索:

void pop()
{
    if (size)
    {
        queue *ptr=head;
        head=head->next;
        if (head) head->prev=NULL;
        free(ptr);
    }
}
int front() 
{
   return head->val;
}

Also, I guess your aim is to count the smallest number of operations required to produce the desired number from a given one.另外,我想您的目标是计算从给定操作中产生所需数字所需的最少操作次数。 Your cnt variable does not represent the smallest number of operations, it represents the number of times you retrieved an element from the queue.您的cnt变量不代表最少的操作次数,它代表您从队列中检索元素的次数。 You need to increment it for each new level instead.您需要为每个新级别增加它。

Finally, your bfs should return a value even if there is no path from s to d , so you should put return 0;最后,即使没有从sd的路径,你的bfs也应该返回一个值,所以你应该把return 0; after the while(size){} loop.while(size){}循环之后。

UPD. UPD。 You need to skip g[u][j] if it is larger than 2 * (10^4) inside of bfs , otherwise those values be enqueued which is a waste of space.如果g[u][j]大于bfs内的2 * (10^4) ,则需要跳过它,否则这些值会被排队,这会浪费空间。 By the way your v array has only 2222 elements, it should have at least 20001 ( v[20000] is the last one)顺便说一句,您的v数组只有 2222 个元素,它应该至少有 20001 ( v[20000]是最后一个)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM