DFS and BFS
Preface
最近在看数据结构与算法,当前进度到DFS和BFS。
网上内容尤其是代码内容鱼龙混杂,因此mark一下正确可运行的DFS和BFS。亲测可用,放心食用。
代码内容借鉴:
https://www.cnblogs.com/Luoters/p/12033473.html
基于该代码,修改了部分语法错误。
Breief Introduction
DFS: Depth First Search 深度优先搜索
BFS: Breadth First Search 广度优先搜索
DFS和BFS是两种图遍历的方式。二者都是按照约定规则对图进行遍历。
DFS的主要实现是通过递归和回溯。与树中的前序、中序、遍历相似,按既定规则一条路走到黑,若此路不通则退回到有其他方式的路上继续遍历,因此会遍历所有的可能路径,时间消耗更多一些。
BFS的主要实现靠逻辑遍历。与树中的层序遍历类似,按既定规则把每个元素的可能路径探索一遍,一层一层进行,这其中需要新建一个队列帮助,因此空间消耗更多一些。
另外,BFS的优势还在于,能够连续找到与同一元素关联的数据。
图的表示主要有邻接矩阵和邻接表两种,因此分别基于图的这两种表示方法实现DFS和BFS。
多说无益,直接上代码。
Code
Based on Adjacent Matrix
基于邻接矩阵
的无向图
,分别实现DFS
和BFS
。
DFS Based on Adjacent Matrix
#include <iostream>
#define MAXNUM 10
using namespace std;
typedef struct
{
int vnum;
int anum;
char ver[MAXNUM];
char arc[MAXNUM][MAXNUM];
}MGraph;
int Location(MGraph& G, char e)
{
for (int i = 0; i < G.vnum; i++)
{
if (G.ver[i] == e)
return i;
}
return -1;
}
bool CreateGraph(MGraph& G, int vnum, int anum, char v[], char a[])
{
G.vnum = vnum;
G.anum = anum;
for (int i = 0; i < G.vnum; i++)
{
G.ver[i] = v[i];
}
for (int i = 0; i < G.vnum; i++)
{
for (int j = 0; j < G.vnum; j++)
{
G.arc[i][j] = 0;
}
}
int t = 0;
for (int i = 0; i < G.vnum; i++)
{
char m = a[t++];
char n = a[t++];
t++;
t++;
int p = Location(G, m);
int q = Location(G, n);
G.arc[p][q] = 1;
G.arc[q][p] = 1;
}
return true;
}
int FirstAdjVex(MGraph& G, int i)
{
for (int j = 0; j < G.vnum; j++)
{
if (G.arc[i][j] == 1)
{
return j;
}
}
return -1;
}
int NextAdjVex(MGraph& G, int i, int j)
{
for (int k = j+1; k < G.vnum; k++)
{
if (G.arc[i][k] == 1)
{
return k;
}
}
return -1;
}
int visited[MAXNUM];
void DFS(MGraph& G, int i)
{
visited[i] = 1;
cout << G.ver[i] << endl;
int k = FirstAdjVex(G, i);
cout << "first " << G.ver[i] << " to " << G.ver[k] << endl;
while (k != -1)
{
if(visited[k] == 0)
{
cout << G.ver[k] << endl;
visited[k] = 1;
DFS(G, k);
}
k = NextAdjVex(G, i, k);
cout << "next " << G.ver[i] << " to " << G.ver[k] << endl;
}
}
void DFSTraverse(MGraph& G)
{
for (int i = 0; i < G.vnum; i++)
{
visited[i] = 0;
}
for (int i = 0; i < G.vnum; i++)
{
if (visited[i] == 0)
{
DFS(G, i);
}
}
}
int main()
{
char v[] = "abcdef";
char a[] = "ab, ac, ad, be, ce, df";
MGraph G;
CreateGraph(G, 6, 6, v, a);
DFSTraverse(G);
return 0;
}
输出结果如下:
a
first a to b
b
b
first b to a
next b to e
e
e
first e to b
next e to c
c
c
first c to a
next c to e
next c to
next e to
next b to
next a to c
next a to d
d
d
first d to a
next d to f
f
f
first f to d
next f to
next d to
next a to
BFS Based on Adjacent Matrix
#include <iostream>
#define MAXNUM 10
using namespace std;
typedef struct
{
int vnum;
int anum;
char ver[MAXNUM];
char arc[MAXNUM][MAXNUM];
}MGraph;
int Location(MGraph& G, char e)
{
for (int i = 0; i < G.vnum; i++)
{
if (G.ver[i] == e)
return i;
}
return -1;
}
bool CreateGraph(MGraph& G, int vnum, int anum, char v[], char a[])
{
G.vnum = vnum;
G.anum = anum;
for (int i = 0; i < G.vnum; i++)
{
G.ver[i] = v[i];
}
for (int i = 0; i < G.vnum; i++)
{
for (int j = 0; j < G.vnum; j++)
{
G.arc[i][j] = 0;
}
}
int t = 0;
for (int i = 0; i < G.vnum; i++)
{
char m = a[t++];
char n = a[t++];
t++;
t++;
int p = Location(G, m);
int q = Location(G, n);
G.arc[p][q] = 1;
G.arc[q][p] = 1;
}
return true;
}
int FirstAdjVex(MGraph& G, int i)
{
for (int j = 0; j < G.vnum; j++)
{
if (G.arc[i][j] == 1)
{
return j;
}
}
return -1;
}
int NextAdjVex(MGraph& G, int i, int j)
{
for (int k = j+1; k < G.vnum; k++)
{
if (G.arc[i][k] == 1)
{
return k;
}
}
return -1;
}
typedef struct QNode
{
char data;
QNode* next;
}QNode, *QueuePtr;
typedef struct
{
QueuePtr first;
QueuePtr last;
}LinkQueue;
bool InitQueue(LinkQueue& Q)
{
Q.first = (QNode*)malloc(sizeof(QNode));
if (!Q.first) return false;
Q.first->next = NULL;
Q.last = Q.first;
return true;
}
bool EnQueue(LinkQueue& Q, char e)
{
auto q = (QNode*)malloc(sizeof(QNode));
if (!q) return false;
q->data = e;
q->next = NULL;
Q.last->next = q;
Q.last = q;
return true;
}
bool DeQueue(LinkQueue& Q, char& e)
{
if (Q.first == Q.last)
return false;
auto q = Q.first->next;
if (q != NULL)
{
Q.first->next = q->next;
e = q->data;
}
if(q == Q.last)
{
Q.last = Q.first;
}
return true;
}
bool EmptyQueue(LinkQueue& Q)
{
if (Q.first == Q.last)
return true;
return false;
}
int visited[MAXNUM];
void BFS(MGraph& G)
{
for (int i = 0; i < G.vnum; i++)
{
visited[i] = 0;
}
LinkQueue Q;
InitQueue(Q);
for (int i = 0; i < G.vnum; i++)
{
if (visited[i] == 0)
{
EnQueue(Q, G.ver[i]);
visited[i] = 1;
cout << G.ver[i] << endl;
while (!EmptyQueue(Q))
{
char e;
DeQueue(Q, e);
int v = Location(G, e);
int w = FirstAdjVex(G, v);
while (w != -1)
{
if (visited[w] == 0)
{
EnQueue(Q, G.ver[w]);
visited[w] = 1;
cout << G.ver[w] << endl;
}
w = NextAdjVex(G, v, w);
}
}
}
}
return;
}
int main()
{
char v[] = "abcdef";
char a[] = "ab, ac, ad, be, ce, df";
MGraph G;
CreateGraph(G, 6, 6, v, a);
BFS(G);
return 0;
}
Based on Adjacent List
基于邻接表
的无向图
,分别实现DFS
和BFS
。
DFS Based on Adjacent List
#include <iostream>
#define MAXNUM 10
using namespace std;
typedef struct ANode
{
int AdjVex;
ANode* next;
}ANode;
typedef struct VNode
{
char data;
ANode *firstArc;
};
typedef struct
{
int vnum;
int anum;
VNode vex[MAXNUM];
}ALGraph;
int Location(ALGraph& G,char e)
{
for (int i = 0; i < G.vnum; i++)
{
if (G.vex[i].data == e)
return i;
}
return -1;
}
bool CreateGraph(ALGraph& G, int vnum, int anum, char v[], char a[])
{
G.vnum = vnum;
G.anum = anum;
for (int i = 0; i < G.vnum; i++)
{
G.vex[i].data = v[i];
G.vex[i].firstArc = NULL;
}
int t = 0;
for (int i = 0; i < G.vnum; i ++)
{
char m = a[t++];
char n = a[t++];
t++;
t++;
int p = Location(G, m);
int q = Location(G, n);
ANode *p1, *p2, *p3;
p1 = (ANode*)malloc(sizeof(ANode));
p1->AdjVex = p;
p1->next = NULL;
if (G.vex[q].firstArc == NULL)
{
G.vex[q].firstArc = p1;
}
else
{
p3 = G.vex[q].firstArc;
while (p3->next)
{
p3 = p3->next;
}
p3->next = p1;
}
p2 = (ANode*)malloc(sizeof(ANode));
p2->AdjVex = q;
p2->next = NULL;
if (G.vex[p].firstArc == NULL)
{
G.vex[p].firstArc = p2;
}
else
{
p3 = G.vex[p].firstArc;
while(p3->next)
{
p3 = p3->next;
}
p3->next = p2;
}
}
return true;
}
int FirstAdjVex(ALGraph& G, int i)
{
if (G.vex[i].firstArc)
return G.vex[i].firstArc->AdjVex;
return -1;
}
int NextAdjVex(ALGraph& G, int i, int j)
{
auto p = G.vex[i].firstArc;
if (p->AdjVex == j and p->next)
return p->next->AdjVex;
else if(p->next)
p = p->next;
return -1;
}
int visited[MAXNUM];
void DFS(ALGraph &G, int i)
{
visited[i] = 1;
cout << G.vex[i].data << endl;
int k = FirstAdjVex(G, i);
cout << "first " << G.vex[i].data << " to " << G.vex[k].data << endl;
while (k != -1)
{
if(visited[k] == 0)
{
cout << G.vex[k].data << endl;
visited[k] = 1;
DFS(G, k);
}
k = NextAdjVex(G, i, k);
cout << "next " << G.vex[i].data << " to " << G.vex[k].data << endl;
}
}
void DFSTraverse(ALGraph & G)
{
for (int i = 0; i < G.vnum; i++)
{
visited[i] = 0;
}
for (int i = 0; i < G.vnum; i++)
{
if (visited[i] == 0)
{
DFS(G, i);
}
}
}
int main()
{
char v[] = "abcdef";
char a[] = "ab, ac, ad, be, ce, df";
ALGraph G;
CreateGraph(G, 6, 6, v, a);
// BFS(G);
DFSTraverse(G);
return 0;
}
输出结果如下:
a
first a to b
b
b
first b to a
next b to e
e
e
first e to b
next e to c
c
c
first c to a
next c to e
next c to L
next e to L
next b to L
next a to c
next a to L
d
first d to a
next d to f
f
f
first f to d
next f to L
next d to L
BFS Based on Adjacent List
#include <iostream>
#define MAXNUM 10
using namespace std;
typedef struct ANode
{
int AdjVex;
ANode* next;
}ANode;
typedef struct VNode
{
char data;
ANode *firstArc;
};
typedef struct
{
int vnum;
int anum;
VNode vex[MAXNUM];
}ALGraph;
int Location(ALGraph& G,char e)
{
for (int i = 0; i < G.vnum; i++)
{
if (G.vex[i].data == e)
return i;
}
return -1;
}
bool CreateGraph(ALGraph& G, int vnum, int anum, char v[], char a[])
{
G.vnum = vnum;
G.anum = anum;
for (int i = 0; i < G.vnum; i++)
{
G.vex[i].data = v[i];
G.vex[i].firstArc = NULL;
}
int t = 0;
for (int i = 0; i < G.vnum; i ++)
{
char m = a[t++];
char n = a[t++];
t++;
t++;
int p = Location(G, m);
int q = Location(G, n);
ANode *p1, *p2, *p3;
p1 = (ANode*)malloc(sizeof(ANode));
p1->AdjVex = p;
p1->next = NULL;
if (G.vex[q].firstArc == NULL)
{
G.vex[q].firstArc = p1;
}
else
{
p3 = G.vex[q].firstArc;
while (p3->next)
{
p3 = p3->next;
}
p3->next = p1;
}
p2 = (ANode*)malloc(sizeof(ANode));
p2->AdjVex = q;
p2->next = NULL;
if (G.vex[p].firstArc == NULL)
{
G.vex[p].firstArc = p2;
}
else
{
p3 = G.vex[p].firstArc;
while(p3->next)
{
p3 = p3->next;
}
p3->next = p2;
}
}
return true;
}
int FirstAdjVex(ALGraph& G, int i)
{
if (G.vex[i].firstArc)
return G.vex[i].firstArc->AdjVex;
return -1;
}
int NextAdjVex(ALGraph& G, int i, int j)
{
auto p = G.vex[i].firstArc;
if (p->AdjVex == j and p->next)
return p->next->AdjVex;
else if(p->next)
p = p->next;
return -1;
}
typedef struct QNode
{
char data;
QNode* next;
}QNode, *QueuePtr;
typedef struct
{
QueuePtr first;
QueuePtr last;
}LinkQueue;
bool InitQueue(LinkQueue& Q)
{
Q.first = (QNode*)malloc(sizeof(QNode));
if (!Q.first) return false;
Q.first->next = NULL;
Q.last = Q.first;
return true;
}
bool EnQueue(LinkQueue& Q, char e)
{
auto q = (QNode*)malloc(sizeof(QNode));
if (!q) return false;
q->data = e;
q->next = NULL;
Q.last->next = q;
Q.last = q;
return true;
}
bool DeQueue(LinkQueue& Q, char& e)
{
if (Q.first == Q.last)
return false;
auto q = Q.first->next;
if (q != NULL)
{
Q.first->next = q->next;
e = q->data;
}
if(q == Q.last)
{
Q.last = Q.first;
}
return true;
}
bool EmptyQueue(LinkQueue& Q)
{
if (Q.first == Q.last)
return true;
return false;
}
int visited[MAXNUM];
void BFS(ALGraph& G)
{
for (int i = 0; i < G.vnum; i++)
{
visited[i] = 0;
}
LinkQueue Q;
InitQueue(Q);
for (int i = 0; i < G.vnum; i++)
{
if (visited[i] == 0)
{
EnQueue(Q, G.vex[i].data);
visited[i] = 1;
cout << G.vex[i].data << endl;
while (!EmptyQueue(Q))
{
char e;
DeQueue(Q, e);
int v = Location(G, e);
int w = FirstAdjVex(G, v);
while (w != -1)
{
if (visited[w] == 0)
{
EnQueue(Q, G.vex[w].data);
visited[w] = 1;
cout << G.vex[w].data << endl;
}
w = NextAdjVex(G, v, w);
}
}
}
}
return;
}
int main()
{
char v[] = "abcdef";
char a[] = "ab, ac, ad, be, ce, df";
ALGraph G;
CreateGraph(G, 6, 6, v, a);
BFS(G);
// DFSTraverse(G);
return 0;
}