/ *このテーマに関する他の偉大な神々のコードを読んだ後、私はそれらを自分で書きました。いくつかの場所は私にとって少し難しい、初心者のデータ構造を持つ初心者です。変更が完了した後、理解できない場合は、MOOCに移動して、オンラインコースを見て理解することができます。* /
N個の頂点とE個のエッジを持つ無向グラフを前提として、DFSとBFSを使用して、接続されているすべてのセットを一覧表示します。頂点に0からN-1までの番号が付けられているとします。検索を実行するときは、常に最も番号の小さい頂点から開始し、番号の昇順で隣接するポイントを訪問すると想定されています。
入力形式:
最初の行を入力して、2つの整数N(0 <N≤10)とEを指定します。これらはそれぞれ、グラフの頂点とエッジの数です。次に、ラインEで、各ラインはエッジの2つの端点を示します。各行の番号は1スペースで区切られます。
出力フォーマット:
「{v1 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 中国大学MOOC 浙大 数据结构 第六讲 图(上)
2 DFS
作者:拉风小宇
来源:CSDN
原文:https://blog.csdn.net/lafengxiaoyu/article/details/53493080
版权声明:本文为博主原创文章,转载请附上博文链接!
3 BFS
作者:拉风小宇
来源:CSDN
原文:https://blog.csdn.net/lafengxiaoyu/article/details/53502873
版权声明:本文为博主原创文章,转载请附上博文链接!*/
#include <stdio.h>
#include <stdlib.h>
/* 图的邻接矩阵表示法 */
#define MaxVertexNum 100 /* 最大顶点数设为100 */
#define INFINITY 65535 /* ∞设为双字节无符号整数的最大值65535*/
int Visited[MaxVertexNum];/* 标记V已访问 */
#define ERROR 0
typedef int Vertex; /* 用顶点下标表示顶点,为整型 */
typedef int WeightType; /* 边的权值设为整型 */
//typedef char DataType; /* 顶点存储的数据类型设为字符型 */
typedef int ElementType;
typedef int Position;
/* 边的定义 */
typedef struct ENode *PtrToENode;
struct ENode{
Vertex V1, V2; /* 有向边<V1, V2> */
WeightType Weight; /* 权重 */
};
typedef PtrToENode Edge;
/* 图结点的定义 */
typedef struct GNode *PtrToGNode;
struct GNode{
int Nv; /* 顶点数 */
int Ne; /* 边数 */
WeightType G[MaxVertexNum][MaxVertexNum]; /* 邻接矩阵 */
//DataType Data[MaxVertexNum]; /* 存顶点的数据 */
/* 注意:很多情况下,顶点无数据,此时Data[]可以不用出现 */
};
typedef PtrToGNode MGraph; /* 以邻接矩阵存储的图类型 */
struct Node {
int Data;
struct Node *Next;
};
struct QNode {
struct Node *rear;
struct Node *front;
};
typedef struct QNode *Queue;
MGraph CreateGraph( int VertexNum );
void InsertEdge( MGraph Graph, Edge E );
MGraph BuildGraph();
void Visit(Vertex V);
int IsEmpty(Queue Q);
Queue CreateQueue();
int DeleteQ(Queue PtrQ);
void InsertQ(int item, Queue PtrQ);
bool IsEdge(MGraph Graph, Vertex V, Vertex W);
void BFS(MGraph Graph, Vertex S, void(*Visit)(Vertex));
void ListComponentsBFS(MGraph Graph);
void DFS(MGraph Graph, Vertex V, void(*Visit)(Vertex));
void ListComponentsDFS(MGraph Graph);
int main()
{
MGraph Graph;
Graph = BuildGraph();
for (int i = 0; i < MaxVertexNum; i++) {
Visited[i] = false;
}
//printf("下面执行DFS\n");
ListComponentsDFS( Graph );
/* 在执行完 ListComponentsDFS( Graph ); 后,需重置 Visited[i]
否则 ListComponentsBFS( Graph ); 执行不了。。。 */
for (int i = 0; i < MaxVertexNum; i++) {
Visited[i] = false;
}
//printf("下面执行BFS\n");
ListComponentsBFS( Graph );
return 0;
}
MGraph CreateGraph( int VertexNum )
{ /* 初始化一个有VertexNum个顶点但没有边的图 */
Vertex V, W;
MGraph Graph;
Graph = (MGraph)malloc(sizeof(struct GNode)); /* 建立图 */
Graph->Nv = VertexNum;
Graph->Ne = 0;
/* 初始化邻接矩阵 */
/* 注意:这里默认顶点编号从0开始,到(Graph->Nv - 1) */
for (V=0; V<Graph->Nv; V++)
for (W=0; W<Graph->Nv; W++)
Graph->G[V][W] = INFINITY;
//printf("图初始化完成\n");
return Graph;
}
void InsertEdge( MGraph Graph, Edge E )
{
/* 插入边 <V1, V2> */
Graph->G[E->V1][E->V2] = E->Weight;
/* 若是无向图,还要插入边<V2, V1> */
Graph->G[E->V2][E->V1] = E->Weight;
}
MGraph BuildGraph()
{
MGraph Graph;
Edge E;
Vertex V;
int Nv, Ne, i;
//printf("输入顶点数\n");
scanf("%d %d", &Nv, &Ne); /* 读入顶点个数 */
Graph = CreateGraph(Nv); /* 初始化有Nv个顶点但没有边的图 */
Graph->Ne = Ne;
//printf("输入边数\n");
//scanf("%d", &(Graph->Ne)); /* 读入边数 */
if ( Graph->Ne != 0 ) { /* 如果有边 */
E = (Edge)malloc(sizeof(struct ENode)); /* 建立边结点 */
/* 读入边,格式为"起点 终点 权重",插入邻接矩阵 */
for (i=0; i<Graph->Ne; i++) {
//printf("输入一条边的两个端点\n");
scanf("%d %d", &E->V1, &E->V2);
E->Weight = 1;
/* 注意:如果权重不是整型,Weight的读入格式要改 */
InsertEdge( Graph, E );
}
}
/* 如果顶点有数据的话,读入数据 */
//for (V=0; V<Graph->Nv; V++)
// scanf(" %c", &(Graph->Data[V]));
//printf("图建立完成\n");
return Graph;
}
void Visit(Vertex V)
{
printf("正在访问顶点%d\n", V + 1);
}
int IsEmpty(Queue Q) {
return(Q->front == NULL);
};
Queue CreateQueue() {
Queue PtrQ;
PtrQ = (Queue)malloc(sizeof(struct QNode));
struct Node *rear;
struct Node *front;
rear = (Node*)malloc(sizeof(struct Node));
rear = NULL;
front = (Node*)malloc(sizeof(struct Node));
front = NULL;
PtrQ->front = front;
PtrQ->rear = rear;
return PtrQ;
};
int DeleteQ(Queue PtrQ) {
struct Node *FrontCell;
int FrontElem;
if (IsEmpty(PtrQ)) {
printf("队列空");
return ERROR;
}
FrontCell = PtrQ->front;
if (PtrQ->front == PtrQ->rear)
PtrQ->front = PtrQ->rear = NULL;
else {
PtrQ->front = PtrQ->front->Next;
}
FrontElem = FrontCell->Data;
free(FrontCell);
return FrontElem;
}
void InsertQ(int item, Queue PtrQ) {
struct Node *FrontCell;
FrontCell = (Node*)malloc(sizeof(struct Node));
FrontCell->Data = item;
FrontCell->Next = NULL;
if (IsEmpty(PtrQ)) {
PtrQ->front = FrontCell;
PtrQ->rear = FrontCell;
}
else {
PtrQ->rear->Next = FrontCell;
PtrQ->rear = FrontCell;
}
};
/* 邻接矩阵存储的图 - BFS */
/* IsEdge(Graph, V, W)检查<V, W>是否图Graph中的一条边,即W是否V的邻接点。 */
/* 此函数根据图的不同类型要做不同的实现,关键取决于对不存在的边的表示方法。*/
/* 例如对有权图, 如果不存在的边被初始化为INFINITY, 则函数实现如下: */
bool IsEdge(MGraph Graph, Vertex V, Vertex W)
{
return Graph->G[V][W]<INFINITY ? true : false;
}
/* Visited[]为全局变量,已经初始化为false
在main函数中执行 */
void BFS(MGraph Graph, Vertex S, void(*Visit)(Vertex))
{ /* 以S为出发点对邻接矩阵存储的图Graph进行BFS搜索 */
Queue Q;
Vertex V, W;
Q = CreateQueue(); /* 创建空队列, MaxSize为外部定义的常数 */
/* 访问顶点S:此处可根据具体访问需要改写 */
//Visit(S);
Visited[S] = true; /* 标记S已访问 */
InsertQ(S, Q); /* S入队列 */
printf("{");
while (!IsEmpty(Q)) {
V = DeleteQ(Q); /* 弹出V */
printf(" %d", V);
for (W = 0; W<Graph->Nv; W++) /* 对图中的每个顶点W */
/* 若W是V的邻接点并且未访问过 */
if (!Visited[W] && IsEdge(Graph, V, W)) {
/* 访问顶点W */
//Visit(W);
Visited[W] = true; /* 标记W已访问 */
InsertQ(W, Q); /* W入队列 */
}
} /* while结束*/
printf(" }\n");
}
void ListComponentsBFS(MGraph Graph)
{
int V;
for (V=0; V<Graph->Nv; V++) {
if (!Visited[V]) {
BFS(Graph, V, Visit);
}
}
}
void DFS(MGraph Graph, Vertex V, void(*Visit)(Vertex))
{ /* 以V为出发点对邻接表存储的图Graph进行DFS搜索 */
Vertex W;
//Visit(V); /* 访问第V个顶点 */
Visited[V] = true; /* 标记V已访问 */
printf(" %d", V);
for (W = 0; W<Graph->Nv;W++ ) /* 对V的每个邻接点W */
if ((!Visited[W])&&(Graph->G[V][W]==1)) /* 若未被访问 */
DFS(Graph, W, Visit); /* 则递归访问之 */
}
void ListComponentsDFS(MGraph Graph)
{
int V;
for (V=0; V<Graph->Nv; V++) {
if (!Visited[V]) {
printf("{");
DFS(Graph, V, Visit);
printf(" }\n");
}
}
}