这道题真是雪崩啊,!一个晚上做的DFS,发现遍历竟然是从小到大,诶,我辛辛苦苦用邻接表把他实现了一遍,发现每个连通集的数字顺序呢不对啊!。。为了纪念我逝去的时间,我还是打算先把我写的用邻接表储存的DFS贴出来!!!明天再码邻接矩阵实现!惯例,先贴题目。
给定一个有N个顶点和E条边的无向图,请用DFS和BFS分别列出其所有的连通集。假设顶点从0到N−1编号。进行搜索时,假设我们总是从编号最小的顶点出发,按编号递增的顺序访问邻接点。
输入第1行给出2个整数N(E,分别是图的顶点数和边数。随后E行,每行给出一条边的两个端点。每行中的数字之间用1空格分隔。 )和
按照"{ v1 v2 ... vk }"的格式,每行输出一个连通集。先输出DFS的结果,再输出BFS的结果。
8 6
0 7
0 1
2 0
4 1
2 4
3 5
{ 0 1 4 2 7 }
{ 3 5 }
{ 6 }
{ 0 1 2 7 4 }
{ 3 5 }
{ 6 }
先贴出我没看清题目,用邻接表来实现的,答案其实本质一样的,但是顺序就会出现问题。!还有几点需要注意:
1、对于无向图的邻接表储存,需要储存两次,比如1和3相连,在1的顶点域的后面写3,同样3的顶点域后面也得写1.
2、对于链表的插入问题,我已经好几次都把插入的顶点放在链表最后,导致的问题就是太麻烦!!!,重要的事情说三遍,如果不是模拟队列,把插入的结点放在头结点后面!!!!
#include"stdio.h"
#include"stdlib.h"
#define MaxVertex 10
#define TRUE 1
#define FALSE 0
#define SEPARATE 10
#define PATHCOUNT 20
int visit[MaxVertex]; //标记结点是否被访问,被访问为TRUE,反之为FALSE
int path[PATHCOUNT]; //储存路径,每个连通分量之间用SEPARATE分开
int count=0; //路径计数位
typedef struct Node //用邻接表来表示图,需要边表结点声明和顶点表结点声明
{
int AdjV;
struct Node* Next;
}EdgeNode;
typedef struct Vnode
{
int Vertex;
EdgeNode* FirstEdge;
}VertexNode;
typedef VertexNode AdjList[MaxVertex];
typedef struct
{
AdjList Adjlist;
int n,e;
}UgGraph;
void CreateUgGraph(UgGraph* G) //开始读取顶点的信息
{
int i,j,k;
EdgeNode* edge;
EdgeNode* preedge;
scanf("%d",&(G->n));
scanf("%d",&(G->e));
for(i=0;in;i++)
{
G->Adjlist[i].FirstEdge=NULL;
G->Adjlist[i].Vertex=i;
}
for(i=0;ie;i++) //开始读取边的信息
{
scanf("%d %d",&j,&k);
edge=(EdgeNode*)malloc(sizeof(struct Node)); //把结点接在顶点域的后面,而不是链表最后这样比较简便
edge->AdjV=k;
edge->Next=G->Adjlist[j].FirstEdge;
G->Adjlist[j].FirstEdge=edge;
edge=(EdgeNode*)malloc(sizeof(struct Node)); //无向图再生成一个结点,表示反向结点
edge->AdjV=j;
edge->Next=G->Adjlist[k].FirstEdge;
G->Adjlist[k].FirstEdge=edge;
}
return;
}
void vistFunc(int V);
void DFS(UgGraph* G,int V) //单个连通分量的遍历
{
EdgeNode* temp;
visit[V]=TRUE;
path[count]=V;
count++;
for(temp=G->Adjlist[V].FirstEdge;temp;temp=temp->Next)
if(!visit[temp->AdjV])
DFS(G,temp->AdjV);
return;
}
void DFS_all(UgGraph* G)
{
int i;
for(i=0;in;i++)
{
visit[i]=FALSE;
}
for(i=0;in;i++)
{
if(!visit[i])
DFS(G,i);
path[count]=SEPARATE;
count++;
}
}
int main()
{
UgGraph G;
CreateUgGraph(&G);
DFS_all(&G);
return 0;
}
明天再写能AC的代码!
———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
把昨天没做完的事情做完!
其实代码很快就写完了,但是测试就是不对,仔仔细细看了几遍DFS和BFS的代码也没错啊。后来百度了下别人的C代码,一个函数一个函数检查,发现竟然是Create邻接矩阵那里初始化写j的初始化写成i了汗汗汗汗!!!!浪费了我好几个小时!!!下面给出AC了的代码吧!!
#include"stdio.h"
#include"stdlib.h"
#define MaxVertexNum 15
#define TRUE 1
#define FALSE 0
int Visit[MaxVertexNum];
typedef struct QNode /* 队列的创建 */
{
int data;
struct QNode *next;
}QNode,*QueuePtr;
typedef struct /* 队列的链表结构 */
{
QueuePtr front,rear; /* 队头、队尾指针 */
}LinkQueue;
void InitQueue(LinkQueue *Q)
{
Q->front=Q->rear=(QueuePtr)malloc(sizeof(QNode));
Q->front->next=NULL;
return;
}
int QueueEmpty(LinkQueue Q)
{
if(Q.front==Q.rear)
return TRUE;
else
return FALSE;
}
void EnQueue(LinkQueue *Q,int e)
{
QueuePtr s=(QueuePtr)malloc(sizeof(QNode));
s->data=e;
s->next=NULL;
Q->rear->next=s; /* 把拥有元素e的新结点s赋值给原队尾结点的后继 */
Q->rear=s; /* 把当前的s设置为队尾结点,rear指向s */
return;
}
int DeQueue(LinkQueue *Q)
{
QueuePtr p;
int DelteElemennt;
p=Q->front->next; /* 将欲删除的队头结点暂存给p,见图中① */
DelteElemennt=p->data; /* 将欲删除的队头结点的值赋值给e */
Q->front->next=p->next;/* 将原队头结点的后继p->next赋值给头结点后继,见图中② */
if(Q->rear==p) /* 若队头就是队尾,则删除后将rear指向头结点,见图中③ */
Q->rear=Q->front;
free(p);
return DelteElemennt;
}
//因为这里顶点就是用0,1,2,3...来表示,并且不需要储存顶点信息,因此就做一个二维数组就OK
typedef struct //int型二维数组,INFINITY表示两结点没直接相连,1代表相连
{
int Edges[MaxVertexNum][MaxVertexNum];
int n,e; //顶点数和边数
}MGraph;
void CreateMGraph(MGraph* G)
{
int i,j,k;
scanf("%d %d",&G->n,&G->e);
for(i=0;in;i++)
for(j=0;jn;j++)
G->Edges[i][j]=0;
for(i=0;ie;i++)
{
scanf("%d %d",&j,&k);
G->Edges[j][k]=1;
G->Edges[k][j]=1;
}
return;
}
void DFS(MGraph* G,int V)
{
int i;
Visit[V]=TRUE;
printf("%d ",V);
for(i=0;in;i++)
{
if(!Visit[i]&&G->Edges[V][i])
DFS(G,i);
}
return;
}
void DFS_MG(MGraph* G)
{
int i;
for(i=0;in;i++)
Visit[i]=FALSE;
for(i=0;in;i++)
{
if(!Visit[i])
{
printf("{ ");
DFS(G,i);
printf("}\n");
}
}
return;
}
void BFS(MGraph* G,int V)
{
LinkQueue Q;
int i,j;
InitQueue(&Q);
EnQueue(&Q,V);
Visit[V]=TRUE;
while(!QueueEmpty(Q))
{
j=DeQueue(&Q);
printf("%d ",j);
for(i=0;in;i++)
{
if(!Visit[i]&&G->Edges[j][i])
{
EnQueue(&Q,i);
Visit[i]=TRUE;
}
}
}
}
void BFS_MG(MGraph* G)
{
int i;
for(i=0;in;i++)
{
Visit[i]=FALSE;
}
for(i=0;in;i++)
{
if(!Visit[i])
{
printf("{ ");
BFS(G,i);
printf("}\n");
}
}
return;
}
int main()
{
MGraph G;
CreateMGraph(&G);
DFS_MG(&G);//下面开始BFS
BFS_MG(&G);
return 0;
}