这里实现的BFS算法在Cormen中提到。但是,由于某些原因,此代码会产生无效输出,即使对于普通图形也是如此。创建邻接列表的所有工作都可以正常工作。
以下是整个代码:
#include<stdio.h>
#include<limits.h>
#include<stdlib.h>
#define size 5
struct node *nodelist = NULL;
struct node
{
int nodeid;
int parentid;
int sourcedist;
char *color;
};
struct graph *adjlist = NULL;
struct graph
{
struct listnode *list;
int count;
};
struct listnode
{
int nodeid;
struct listnode *next;
};
struct listnode *createnode(int id)
{
struct listnode *newnode = (struct listnode *)malloc(sizeof(struct listnode));
(*newnode).nodeid = id;
(*newnode).next = NULL;
return newnode;
}
int addtoadjlist(int u, int v)
{
struct listnode *newnode = createnode(v);
if((*(adjlist + u)).list == NULL)
{
(*(adjlist + u)).list = newnode;
(*(adjlist + u)).count++;
}
else
{
(*newnode).next = (*(adjlist + u)).list;
(*(adjlist + u)).list = newnode;
(*(adjlist + u)).count++;
}
}
int disp(int totalnodes)
{
int degreesum = 0, i;
struct listnode *currentnode = NULL;
for(i = 0; i < totalnodes; i++)
{
currentnode = (*(adjlist + i)).list;
printf("\n node %d -> ",i);
while(currentnode != NULL)
{
printf("%d -> ",(*currentnode).nodeid);
currentnode = (*currentnode).next;
}
printf("NULL | Degree: %d",(*(adjlist + i)).count);
degreesum += (*(adjlist + i)).count;
}
return degreesum/2;
}
int dispnodeinfo(int totalnodes)
{
int i;
for(i = 0; i < totalnodes; i++)
{
printf("\n node %d: parent %d| distance from source %d| color %c",(*(nodelist + i)).nodeid,(*(nodelist + i)).sourcedist,(*(nodelist + i)).color);
}
}
int *BFSQf;
int *BFSQr;
int ENQ(int x)
{
if(BFSQr == NULL)
{
BFSQr = BFSQf;
*BFSQf = x;
}
else
{
BFSQr++;
*BFSQr = x;
}
return 0;
}
int DEQ()
{
int temp;
if(BFSQr == NULL)
return -1;
else if(BFSQr == BFSQf)
{
BFSQr = NULL;
return *BFSQf;
}
else
{
temp = *BFSQr;
BFSQr--;
return temp;
}
}
int bfs(int s)
{
(*(nodelist + s)).color = "G";
(*(nodelist + s)).sourcedist = 0;
BFSQr = NULL; //Empty the Queue;
ENQ(s);
while(BFSQr != NULL)
{
int u = DEQ();
struct listnode *currentnode = (*(adjlist + u)).list;
while(currentnode != NULL)
{
int nodeid = (*currentnode).nodeid;
if((*(nodelist + nodeid)).color == "W")
{
(*(nodelist + nodeid)).color = "G";
(*(nodelist + nodeid)).sourcedist = (*(nodelist + u)).sourcedist + 1;
(*(nodelist + nodeid)).parentid = u;
ENQ(nodeid);
}
currentnode = (*currentnode).next;
}
(*(nodelist + u)).color = "B";
}
}
int main(void)
{
int totalnodes, choice = 0, u, v, i, s;
printf("\n Enter the number of nodes in the graph: ");
scanf("%d",&totalnodes);
nodelist = (struct node *)malloc(totalnodes*sizeof(struct node));
for(i = 0; i < totalnodes; i++)
{
(*(nodelist + i)).nodeid = i;
(*(nodelist + i)).parentid = INT_MIN;
(*(nodelist + i)).sourcedist = INT_MAX;
(*(nodelist + i)).color = "W";
}
adjlist = (struct garph *)malloc(totalnodes*sizeof(struct graph));
for(i = 0; i < totalnodes; i++)
{
(*(adjlist + i)).list = NULL;
(*(adjlist + i)).count = 0;
}
while(choice != 3)
{
printf("\n\n 1.) Add Edges. \n 2.) Display \n 3.) Exit. \n Enter your choice: ");
scanf("%d",&choice);
switch(choice)
{
case 1:
printf("\n Enter source and destination vertices for the edge (starting 0): ");
scanf("%d %d",&u,&v);
addtoadjlist(u,v);
//addtoadjlist(v,u);
break;
case 2:
disp(totalnodes);
//printf("\n Total edges = %d ",disp(totalnodes)); only for non directed graphs.
break;
case 3:
break;
default:
printf("\n Invalid input.");
}
}
BFSQf = (int *)malloc(totalnodes*sizeof(int));
BFSQr = NULL; // Queue Empty.
printf("\n Enter source node to apply BFS: ");
scanf("%d",&s);
bfs(s);
dispnodeinfo(totalnodes);
return 0;
}
输入:6 1 0 1 1 0 3 1 1 4 1 4 3 1 3 1 1 2 4 1 2 5 1 5 5 2 3 3
我得到的邻接清单是:
node 0 -> 3 -> 1 -> NULL | Degree: 2
node 1 -> 4 -> NULL | Degree: 1
node 2 -> 5 -> 4 -> NULL | Degree: 2
node 3 -> 1 -> NULL | Degree: 1
node 4 -> 3 -> NULL | Degree: 1
node 5 -> 5 -> NULL | Degree: 1
这是正确的。但产生的结果是:
node 0: parent 2147483647| distance from source 984096070| color
node 1: parent 1| distance from source 984096072| color
node 2: parent 2147483647| distance from source 984096070| color
node 3: parent 0| distance from source 984096072| color
node 4: parent 2| distance from source 984096072| color
node 5: parent 2147483647| distance from source 984096070| color
仅正确分配了节点ID其余都是虚假值。我在main()中的初始赋值后立即调用了displaynodeinfo(),如下所示:
int main(void)
{
....
nodelist = (struct node *)malloc(totalnodes*sizeof(struct node));
for(i = 0; i < totalnodes; i++)
{
(*(nodelist + i)).nodeid = i;
(*(nodelist + i)).parentid = INT_MIN;
(*(nodelist + i)).sourcedist = INT_MAX;
(*(nodelist + i)).color = "W";
}
displaynodeinfo(totalnodes);
.....
}
这里仍然为nodeids分配了虚假的任务。怎么了?请帮忙。
答案 0 :(得分:1)
您的代码有几个问题。对于初学者,启用所有编译器警告并查看它们。在这种情况下,其中一些实际上是真正的错误。下面是每个警告的快速解释(使用GCC编译时)。
因此,在尝试使用代码调试运行时问题之前,请先验证您是否有无警告代码。
<source>: In function 'dispnodeinfo':
<source>:78:62: warning: format '%d' expects argument of type 'int', but argument 4 has type 'char *' [-Wformat=]
printf("\n node %d: parent %d| distance from source %d| color %c",(*(nodelist + i)).nodeid,(*(nodelist + i)).sourcedist,(*(nodelist + i)).color);
~^ ~~~~~~~~~~~~~~~~~~~~~~~
%s
<source>:78:72: warning: format '%c' expects a matching 'int' argument [-Wformat=]
printf("\n node %d: parent %d| distance from source %d| color %c",(*(nodelist + i)).nodeid,(*(nodelist + i)).sourcedist,(*(nodelist + i)).color);
~^
前两个警告已经暗示为什么你在输出中看到“虚假值”。不仅格式字符串具有不匹配类型,而且您还缺少一个参数。
<source>: In function 'bfs':
<source>:131:45: warning: comparison with string literal results in unspecified behavior [-Waddress]
if((*(nodelist + nodeid)).color == "W")
^~
这让您知道将指针与字符串文字进行比较不会达到预期效果。实际上,您应该在结构中使用char
,而不是char *
;然后在整个代码中使用单个字符文字而不是字符串文字('G'
与"G"
)。
<source>: In function 'main':
<source>:160:13: warning: assignment from incompatible pointer type [-Wincompatible-pointer-types]
adjlist = (struct garph *)malloc(totalnodes*sizeof(struct graph));
^
在这里,编译器会警告您类型名称中的拼写错误(struct garph
)。
<source>: In function 'addtoadjlist':
<source>:52:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
<source>: In function 'dispnodeinfo':
<source>:80:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
<source>: In function 'bfs':
<source>:142:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
其余三个警告是关于您声明为返回int
而不是void
的函数,因为它们不会返回任何内容。