列出图的连通集

  • 题目来源:

浙江大学在慕课网上开设的《数据结构》课,陈越老师、何钦铭老师主讲,课后作业的一道题。

  • 题目描述:

  • 思路:

非常基础的一道题,主要考察图的DFS遍历和BFS遍历,最后注意输出的格式就可以了。

  • C语言实现:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

#define MaxVerterNum 100  //最大定点数设为100
#define INFINITY 65535  //无穷设为双字节无符号整数的最大值65535

typedef int WeightType;  //边的权值设为int类型
typedef char DataType;  //顶点存储的数据类型设置为字符类型
typedef int Vertex;  //用顶点下标表示顶点,为整型

bool Visited[MaxVerterNum];

struct QNode
{
	int* Data;  //存储元素的数组
	int Front;  //队列的头指针
	int Rear;  //队列的尾指针
	int MaxSize;  //队列的最大容量
};

//创建一个队列
struct QNode* CreateQueue(int MaxSize)
{
	struct QNode* Q = (struct QNode*)malloc(sizeof(struct QNode));
	Q->Data = (int *)malloc(MaxSize * sizeof(int));
	Q->Front = Q->Rear = 0;
	Q->MaxSize = MaxSize;
	return Q;
}

bool IsFull(struct QNode* Q)
{
	return ((Q->Rear + 1) % Q->MaxSize) == Q->Front;
}

//在队列尾插入一个元素
//参数 struct QNode* Q 要操作的队列
//     int x  待插入的元素
bool AddQ(struct QNode* Q, int x)
{
	if (IsFull(Q))  //判断队列是否为空
	{
		printf("队列满,不能再插入元素\n");
		return false;
	}
	else
	{
		Q->Rear = (Q->Rear + 1) % Q->MaxSize;
		Q->Data[Q->Rear] = x;
		return true;
	}
}

//判断队列是否为空
bool IsEmpty(struct QNode* Q)
{
	return (Q->Front == Q->Rear);
}
//在队列头部删除一个元素
int DeleteQ(struct QNode* Q)
{
	if (IsEmpty(Q))
	{
		printf("队列为空\n");
		return false;
	}
	else
	{
		Q->Front = (Q->Front + 1) % Q->MaxSize;
		return Q->Data[Q->Front];
	}

}

struct GNode 
{
	int Nv;  //顶点数
	int Ne;  //边数
	WeightType G[MaxVerterNum][MaxVerterNum];  //邻接矩阵
	DataType Data[MaxVerterNum][MaxVerterNum];  //存顶点的数据
	/*如果顶点无数据,此时Data[]可以不出现*/
};
//描述边的类型
struct ENode
{
	Vertex V1, V2;  //有向边<V1,V2>
	WeightType Weight;  //权重
};
//作用:初始化一个有VertexNum个顶点但没有边的图
struct GNode* CreateGraph(int VertexNum)
{
	Vertex V, W;
	struct GNode* Graph;
	Graph = (struct GNode*)malloc(sizeof(struct GNode));  //建立图
	Graph->Nv = VertexNum;
	Graph->Ne = 0;

	//初始化邻接矩阵
	for (V = 0;V < Graph->Nv;V++)
	{
		for (W = 0;W < Graph->Nv;W++)
		{
			Graph->G[V][W] = INFINITY;
		}
	}
	return Graph;
}

//作用:在图中插入边
void InsertEdge(struct GNode* Graph,struct ENode* E)
{
	////插入边<V1,V2>
	//Graph->G[E->V1][E->V2] = E->Weight;
	////若是无向图,还需要插入<V2,V1>
	//Graph->G[E->V2][E->V1] = E->Weight;

	//插入边<V1,V2>
	Graph->G[E->V1][E->V2] = 1;
	//若是无向图,还需要插入<V2,V1>
	Graph->G[E->V2][E->V1] = 1;
}
//作用:构建一个图,供主函数调用
struct GNode* BulidGraph()
{
	Vertex V;
	int NV;
	struct ENode* E;
	struct GNode* Graph;
	scanf("%d",&NV);  //读入顶点个数
	Graph = CreateGraph(NV);
	scanf("%d",&(Graph->Ne));  //读入边数

	if (Graph->Ne != 0)
	{
		E = (struct ENode*)malloc(sizeof(struct ENode));
		for (int i = 0;i < Graph->Ne;i++)
		{
			////如果权重不是整型,Weight的读入格式要改
			//scanf("%d %d %d",&E->V1,&E->V2,&E->Weight);
			scanf("%d %d", &E->V1, &E->V2);
			InsertEdge(Graph,E);
		}
	}

	////如果顶点有数据的话,读入数据
	//for (V = 0;V < Graph->Nv;V++)
	//{
	//	scanf("%c",&(Graph->Data[V]));
	//}

	return Graph;
}

void Visit(Vertex V)
{
	printf(" %d",V);
}
//这个DFS是我自己写的
//void DFS(struct GNode* Graph,Vertex V,void(* Visit)(Vertex))
//{
//	Vertex W;
//	Visit(V);
//	Visited[V] = true;
//
//	for (W = V + 1; W < Graph->Nv; W++)
//	{
//		if (Graph->G[V][W] == 1)
//		{
//			if (!Visited[W])
//			{
//				DFS(Graph, W, Visit);
//			}
//		}
//	}
//}

void DFS(struct GNode* Graph, Vertex V, void(*Visit)(Vertex))
{
	Vertex j;
	Visited[V] = true;
	Visit(V);

	for (j = 0;j < Graph->Nv;j++)
	{
		if (Graph->G[V][j] == 1 && !Visited[j])
		{
			DFS(Graph,j,Visit);
		}
	}
}

void DFSTraverser(struct GNode* Graph)
{
	int i = 0;
	//初始化所有顶点都是未访问的状态
	for (i = 0;i < Graph->Nv;i++)
	{
		Visited[i] = false;
	}

	for (i=0;i < Graph->Nv;i++)
	{
		if (!Visited[i])
		{
			printf("{");
			DFS(Graph,i,Visit);    
			printf(" }\n");
		}
	}
}

bool IsEdge(struct GNode* Graph,Vertex V,Vertex W)
{
	return Graph->G[V][W] < INFINITY ? true : false;
}

void BFS(struct GNode* Graph, Vertex S, void(*Visit)(Vertex))
{
	struct QNode* Q;
	Vertex V, W;
	Q = CreateQueue(20);

	Visited[S] = true;
	Visit(S);
	AddQ(Q,S);

	while (!IsEmpty(Q))
	{
		V = DeleteQ(Q);
		for (W = 0;W < Graph->Nv;W++)
		{
			//若W是V的邻接点 并且 没有访问过
			if (!Visited[W] && IsEdge(Graph,V,W))
			{
				Visit(W);  //访问节点
				Visited[W] = true;
				AddQ(Q,W);
			}
		}
	}
}
void BFSTraverser(struct GNode* Graph)
{
	int i = 0;
	//初始化所有顶点都是未访问的状态
	for (i = 0; i < Graph->Nv; i++)
	{
		Visited[i] = false;
	}

	for (i = 0; i < Graph->Nv; i++)
	{
		if (!Visited[i])
		{
			printf("{");
			BFS(Graph, i, Visit);
			printf(" }\n");
		}
	}
}

int main()
{
	struct GNode* Graph = BulidGraph();
	// printf("图建立完毕.\n");
	DFSTraverser(Graph);
	BFSTraverser(Graph);
	// system("pause");
	return 0;
}
posted @ 2019-08-17 09:55  尚修能的技术博客  阅读(532)  评论(0编辑  收藏  举报