深度优先遍历简介
深度优先遍历图的方法是,从图中某顶点v出发:
(1)访问顶点v;
(2)依次从v的未被访问的邻接点出发,对图进行深度优先遍历;直至图中和v有路径相通的顶点都被访问;
(3)若此时图中尚有顶点未被访问,则从一个未被访问的顶点出发,重新进行深度优先遍历,直到图中所有顶点均被访问过为止。 当然,当人们刚刚掌握深度优先搜索的时候常常用它来走迷宫.事实上我们还有别的方法,那就是广度优先搜索(BFS).
实现过程
深度优化搜索可以追溯到Tremaux搜索:
注:图片取自书籍: 算法》 第四版
实现的几个关键步骤:
* 需要标注每一个经过的点,所以我们可以使用一个数组标记是否走过
* 通过递归的方式对顶点之后的节点递归
代码实现
void dfs(AdjGraphPtr a, int *marked, int pos) {
if (*(marked + pos) == 0) { //遍历每个结点
printf("%c\n", a->vertexList[pos]->data);
EdgePtr tmp = a->vertexList[pos]->firstEdge; //边
while (tmp != NULL) {
*(marked + pos) = 1;
dfs(a, marked, _vertexPos(a, tmp->adjvex));
tmp = tmp->next;
}
}
}
void depthFirstSearch(AdjGraphPtr a) {
int length = a->vNum;
int *marked = (int *)malloc(sizeof(int)*length);
memset(marked, 0, sizeof(int)*length);
for (int i = 0; i < length; i++) {
if(*(marked + i) == 0)
dfs(a, marked, i); //first:0
}
free(marked);
}
完整代码:
图:
#include <stdio.h>
#include <malloc.h>
#include <memory.h>
#define MAXVEX 100
#define VTYPE char
typedef struct EdgeNode {
VTYPE adjvex;
int weight;
struct EdgeNode *next;
} Edge, *EdgePtr;
typedef struct VertexNode {
VTYPE data;
EdgePtr firstEdge;
} Vertex, *VertexPtr;
typedef struct {
VertexPtr vertexList[MAXVEX];
int vNum;
} AdjGraph, *AdjGraphPtr;
void freeAdj(AdjGraphPtr a) {
for (int i = 0; i < a->vNum; i++) {
EdgePtr tmp = a->vertexList[i]->firstEdge;
while (tmp->next != NULL) {
EdgePtr t = tmp;
tmp = tmp->next;
free(t);
}
free(tmp);
free(a->vertexList[i]);
}
free(a);
}
EdgePtr createEdgeNode(VTYPE key) {
EdgePtr a = (EdgePtr)malloc(sizeof(Edge));
memset(a, 0, sizeof(Edge));
a->adjvex = key;
a->next = NULL;
return a;
}
int _vertexPos(const AdjGraphPtr m, const VTYPE key) {
for (int i = 0; i < m->vNum; i++) {
if (m->vertexList[i]->data == key)
return i;
}
return -1;
}
void insertVertex(AdjGraphPtr adj, const VTYPE key) {
for (int i = 0; i < adj->vNum; i++) {
if (adj->vertexList[i] == key)
return;
}
VertexPtr vNode = (VertexPtr)malloc(sizeof(Vertex));
memset(vNode, 0, sizeof(Vertex));
vNode->data = key;
vNode->firstEdge = NULL;
adj->vertexList[adj->vNum] = vNode;
adj->vNum++;
}
void insertEdge(AdjGraphPtr adj, VTYPE a, VTYPE b, int weight) {
int pos_a = _vertexPos(adj, a);
EdgePtr avex = createEdgeNode(b);
avex->weight = weight;
if (adj->vertexList[pos_a]->firstEdge == NULL) {
adj->vertexList[pos_a]->firstEdge = avex;
}
else {
EdgePtr tmp = adj->vertexList[pos_a]->firstEdge;
while (tmp->next != NULL) {
tmp = tmp->next;
}
tmp->next = avex;
}
}
AdjGraphPtr createAdjGraph(VTYPE *v, int v_length, int *e, int e_length_1, int e_length_2) {
AdjGraphPtr adj = (AdjGraphPtr)malloc(sizeof(AdjGraph));
memset(adj, 0, sizeof(AdjGraph));
for (int i = 0; i < v_length; i++) {
insertVertex(adj, v[i]);
}
EdgePtr tmp = NULL;
for (int i = 0; i < e_length_1; i++) {
VTYPE a = *(e + e_length_2 * i + 0);
VTYPE b = *(e + e_length_2 * i + 1);
int weight = *(e + e_length_2 * i + 2);
insertEdge(adj, a, b, weight);
}
return adj;
}
void dfs(AdjGraphPtr a, int *marked, int pos) {
if (*(marked + pos) == 0) { //遍历每个结点
printf("%c\n", a->vertexList[pos]->data);
EdgePtr tmp = a->vertexList[pos]->firstEdge; //边
while (tmp != NULL) {
*(marked + pos) = 1;
dfs(a, marked, _vertexPos(a, tmp->adjvex));
tmp = tmp->next;
}
}
}
void depthFirstSearch(AdjGraphPtr a) {
int length = a->vNum;
int *marked = (int *)malloc(sizeof(int)*length);
memset(marked, 0, sizeof(int)*length);
for (int i = 0; i < length; i++) {
if(*(marked + i) == 0)
dfs(a, marked, i); //first:0
}
free(marked);
}
void main() {
int e[13][3] = {
{ 'A', 'F', 60 },
{ 'A', 'E', 30 },
{ 'A', 'C', 10 },
{ 'F', 'A', 60 },
{ 'F', 'E', 20 },
{ 'E', 'A', 30 },
{ 'E', 'D', 50 },
{ 'D', 'E', 50 },
{ 'D', 'C', 11 },
{ 'C', 'D', 11 },
{ 'C', 'A', 10 },
{ 'C', 'B', 5 },
{ 'B', 'C', 5 }
};
const int e_length_1 = 13;
const int e_length_2 = 3;
VTYPE v[6] = { 'A','F','E','D','C','B' };
const int v_length = 6;
AdjGraphPtr adj = createAdjGraph(v, v_length, e, e_length_1, e_length_2);
depthFirstSearch(adj);
freeAdj(adj);
}