06-图1 列出连通集 (邻接表方法)

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

输入格式:
输入第1行给出2个整数N(0<N≤10)和E,分别是图的顶点数和边数。随后E行,每行给出一条边的两个端点。每行中的数字之间用1空格分隔。

输出格式:
按照"{ v​1 v​2​​ … vk}"的格式,每行输出一个连通集。先输出DFS的结果,再输出BFS的结果。

#include <iostream>
#include<cstdlib>
#include<queue>
using namespace std;

#define MaxVertex 100
typedef int WeightType;
typedef int Vertex;

//邻接节点
typedef struct AdjVNode* PtrToAdjVNode;
struct AdjVNode {
	Vertex AdjV;
	WeightType Weight;
	PtrToAdjVNode Next;
};

//头节点
typedef struct VNode* PtrToVNode;
typedef struct VNode {
	PtrToAdjVNode FirstEdge;
	int Data;
} AdjList[MaxVertex];

//图
typedef struct GNode* PtrToGraph;
struct GNode {
	int Nv;
	int Ne;
	AdjList G;
};
typedef PtrToGraph LGraph;

//边
typedef struct ENode* PtrToENode;
struct ENode {
	Vertex V1, V2;
	WeightType Weight;
};
typedef PtrToENode Edge;

bool Visited[MaxVertex] = { false };

//建立空表,有节点无边
LGraph CreateGraph(int VertexNum)
{
	int i;

	LGraph Graph = (LGraph)malloc(sizeof(struct GNode));
	Graph->Nv = VertexNum;
	Graph->Ne = 0;

	for (i = 0; i < Graph->Nv; ++i) {
		Graph->G[i].FirstEdge = NULL;
	}

	return Graph;
}

//插入时排序
void InsertEdge(LGraph Graph, Edge E)
{
	PtrToAdjVNode NewNode;
	PtrToAdjVNode RearNode;

	//无向图V1邻接点
	NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode));
	NewNode->AdjV = E->V2;
	NewNode->Weight = E->Weight;
	//"||"条件前者为真不判断后者:若FirstEdge为NULL or FirstEdge > V2;
	if (!Graph->G[E->V1].FirstEdge || Graph->G[E->V1].FirstEdge->AdjV > E->V2) {
		NewNode->Next = Graph->G[E->V1].FirstEdge;
		Graph->G[E->V1].FirstEdge = NewNode;
	}
	else {
		//找到左侧比新插入节点值小,右侧比新插入节点值大的位置,RearNode->Next > NewNode
		for (RearNode = Graph->G[E->V1].FirstEdge; RearNode->Next && RearNode->Next->AdjV < E->V2; RearNode = RearNode->Next);
		NewNode->Next = RearNode->Next;
		RearNode->Next = NewNode;
	}

	//无向图V2邻接点
	NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode));
	NewNode->AdjV = E->V1;
	NewNode->Weight = E->Weight;
	if (!Graph->G[E->V2].FirstEdge || Graph->G[E->V2].FirstEdge->AdjV > E->V1) {
		NewNode->Next = Graph->G[E->V2].FirstEdge;
		Graph->G[E->V2].FirstEdge = NewNode;
	}
	else {
		for (RearNode = Graph->G[E->V2].FirstEdge; RearNode->Next && RearNode->Next->AdjV < E->V1; RearNode = RearNode->Next);
		NewNode->Next = RearNode->Next;
		RearNode->Next = NewNode;
	}
}

//建立完整表
LGraph BuildGraph()
{
	int Nv, i;
	LGraph Graph;

	cin >> Nv;
	Graph = CreateGraph(Nv);
	cin >> Graph->Ne;
	if (Graph->Ne) {
		Edge E = (Edge)malloc(sizeof(struct ENode));
		for (i = 0; i < Graph->Ne; ++i) {
			cin >> E->V1 >> E->V2;
			InsertEdge(Graph, E);
		}
	}

	return Graph;
}


void Visit(Vertex V) {
	cout << " " << V ;
}

//递归DFS遍历
void DFS(LGraph Graph, Vertex V, void(*Visit)(Vertex))
{
	PtrToAdjVNode W;

	Visit(V);
	Visited[V] = true;		//访问过为true

	for (W = Graph->G[V].FirstEdge; W; W = W->Next) {
		if (!Visited[W->AdjV]) {
			DFS(Graph, W->AdjV, Visit);
		}
	}
}

//利用队列BFS遍历
void BFS(LGraph Graph, Vertex V, void(*Visit)(Vertex))
{
	queue<int> Q;
	PtrToAdjVNode W;

	Visit(V);
	Visited[V] = true;
	Q.push(V);

	while (!Q.empty()) {
		V = Q.front();		//C++ pop不返回值
		Q.pop();
		for (W = Graph->G[V].FirstEdge; W; W = W->Next) {
			if (!Visited[W->AdjV]) {
				Visit(W->AdjV);
				Visited[W->AdjV] = true;
				Q.push(W->AdjV);
			}
		}
	}
}

//还原Visit中的变量为false
void Clear(int Nv)
{
	int i;
	for (i = 0; i < Nv; ++i) {
		Visited[i] = false;
	}
}


int main()
{
	LGraph Graph;
	Vertex V;

	Graph = BuildGraph();

	//开始or结束一个连通分量时输出符号
	for (V = 0; V < Graph->Nv; ++V) {
		if (!Visited[V]) {
			cout << "{";
			DFS(Graph, V, Visit);
			cout << " }" << endl;
		}
	}
	Clear(Graph->Nv);
	for (V = 0; V < Graph->Nv; ++V) {
		if (!Visited[V]) {
			cout << "{";
			BFS(Graph, V, Visit);
			cout << " }" << endl;
		}
	}

	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值