PTA 06-图1 列出连通集

这道题真是雪崩啊,!一个晚上做的DFS,发现遍历竟然是从小到大,诶,我辛辛苦苦用邻接表把他实现了一遍,发现每个连通集的数字顺序呢不对啊!。。为了纪念我逝去的时间,我还是打算先把我写的用邻接表储存的DFS贴出来!!!明天再码邻接矩阵实现!惯例,先贴题目。

给定一个有NN个顶点和EE条边的无向图,请用DFS和BFS分别列出其所有的连通集。假设顶点从0到N-1N1编号。进行搜索时,假设我们总是从编号最小的顶点出发,按编号递增的顺序访问邻接点。

输入格式:

输入第1行给出2个整数NN(00<N10)和EE,分别是图的顶点数和边数。随后EE行,每行给出一条边的两个端点。每行中的数字之间用1空格分隔。

输出格式:

按照"{ v_1v1 v_2v2 ... v_kvk }"的格式,每行输出一个连通集。先输出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;
}

另外我看了下别人写的,队列的创建用了数列,确实比我简单多了,我这里麻烦了些

你可能感兴趣的:(数据结构)