给定一个有N个顶点和E条边的无向图,请用DFS和BFS分别列出其所有的连通集。假设顶点从0到N−1编号。进行搜索时,假设我们总是从编号最小的顶点出发,按编号递增的顺序访问邻接点。
输入格式:
输入第1行给出2个整数N(0<N≤10)和E,分别是图的顶点数和边数。随后E行,每行给出一条边的两个端点。每行中的数字之间用1空格分隔。
输出格式:
按照"{ v1 v2 … 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;
}