深度优先搜索(DFS)的C语言实现(递归与栈实现)

深度优先搜索算法(英语:Depth-First-Search,DFS)是一种用于遍历或搜索树或图的算法。沿着树的深度遍历树的节点,尽可能深的搜索树的分支。当节点v的所在边都己被探寻过,搜索将回溯到发现节点v的那条边的起始节点。这一过程一直进行到已发现从源节点可达的所有节点为止。如果还存在未被发现的节点,则选择其中一个作为源节点并重复以上过程,整个进程反复进行直到所有节点都被访问为止。属于盲目搜索。

DFS 可以使用栈实现也可以使用递归实现,使用递归比较好理解但是在某些语言或者环境下,对规模较大的图使用递归思路会导致栈溢出。

首先是递归版本

#include <bits/stdc++.h>
using namespace std;

#define N 100

// 未访问状态
#define UNDISCOVERED 0
// 已访问状态
#define DISCOVERED 1
// 访问结束状态
#define VISITED 2

int n, M[N][N];
// status:状态	dtime: 访问时间	ftime: 结束访问时间
int status[N], dtime[N], ftime[N];

int _clock;

void dfs_visit(int u){

	status[u] = DISCOVERED;
	dtime[u] = ++_clock;

	for (int v = 0; v < n; v++){
		if (M[u][v] == 0) continue;
		if (status[v] == UNDISCOVERED){
			dfs_visit(v);
		}
	}
	
	ftime[u] = ++_clock;
	status[u] = VISITED;
}

void dfs(){

	for (int u = 0; u < n; u++) status[u] = UNDISCOVERED;
	_clock = 0;
	
	for (int u = 0; u < n; u++){
		if (status[u] == UNDISCOVERED)
			dfs_visit(u);
	}
	for (int u = 0; u < n; u++){
		printf("%d %d %d\n", u+1, dtime[u], ftime[u]);
	}

}

int main(){

	int u, v, k, i, j;

	scanf("%d", &n);
	memset(M, 0, sizeof(M));
	
	for (i = 0; i < n; i++){
		scanf("%d %d", &u, &k);
		u--;
		for (j = 0; j < k; j++){
			scanf("%d", &v);
			v--;
			M[u][v] = 1;
		}
	}

	dfs();

	return 0;
}

栈实现版本

#include <bits/stdc++.h>
using namespace std;

static const int N = 100;

static const int UNDISCOVERED = 0;
static const int DISCOVERED = 1;
static const int VISITED = 2;

int n, M[N][N];
int status[N], dtime[N], ftime[N], _clock;
int next_v[N];

int next(int u){
	for (int v = next_v[u]; v < n; v++){
		next_v[u] = v + 1;
		if (M[u][v]) return v;
	}
	return -1;
}

void dfs_visit(int r){

	stack<int> S;
	S.push(r);
	status[r] = DISCOVERED;
	dtime[r] = ++_clock;

	while(!S.empty()){

		int u = S.top();
		int v = next(u);
		if (v != -1){
			if (status[v] == UNDISCOVERED){
				status[v] = DISCOVERED;
				dtime[v] = ++_clock;
				S.push(v);
			}
		} else {
			S.pop();
			status[u] = VISITED;
			ftime[u] = ++_clock;
		}
	}
}

void dfs(){
	for (int i = 0; i < n; i++){
		status[i] = UNDISCOVERED;
		next_v[i] = 0;
	}
	_clock = 0;

	for (int u = 0; u < n; u++){
		if (status[u] == UNDISCOVERED)
			dfs_visit(u);
	}
	for (int i = 0; i < n; i++){
		cout << i+1 << " " << dtime[i] << " " << ftime[i] << endl;
	}

}

int main()
{

	int u, k, v;

	cin >> n;
	memset(M, 0, sizeof(M));
	
	for (int i = 0; i < n; i++){
		cin >> u >> k;
		u--;
		for (int j = 0; j < k; j++){
			cin >> v;
			v--;
			M[u][v] = 1;
		}
	}

	dfs();

	return 0;
}

递归版本好理解,没啥好说的,重点要说一下栈实现版本中的next函数以及next_v[] 数组

next函数的作用是找该节点的下一个相邻顶点,next_v[] 数组是将图中所有的顶点的访问状态记录下来,这样可以保证当同时有两个节点可以走时,每次都是走编号比较小的那个节点。

参考链接:
[1] 维基百科-深度优先搜索
[2] (日)渡部有隆. 挑战程序设计竞赛 2 算法和数据结构. 北京:人民邮电出版社, 2016.09.

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
深度优先搜索(Depth First Search,DFS)和广度优先搜索(Breadth First Search,BFS)是图的两种常见遍历算法深度优先搜索DFS)是一种用于遍历或搜索树或图的算法。它从根节点开始,沿着一条路径尽可能深入地访问节点,直到达到叶子节点或无法继续前进为止,然后回溯到前一个节点,继续探索其他路径。DFS可以使用递归实现。 以下是C语言实现深度优先搜索的示例代码: ```c #include <stdio.h> #include <stdbool.h> #define MAX_SIZE 100 // 图的邻接矩阵表示 int graph[MAX_SIZE][MAX_SIZE]; bool visited[MAX_SIZE]; // 记录节点是否被访问过 // 深度优先搜索函数 void DFS(int vertex, int num_vertices) { visited[vertex] = true; printf("%d ", vertex); for (int i = 0; i < num_vertices; i++) { if (graph[vertex][i] && !visited[i]) { DFS(i, num_vertices); } } } int main() { int num_vertices, num_edges; printf("请输入图的顶点数和边数:"); scanf("%d %d", &num_vertices, &num_edges); // 初始化图的邻接矩阵 for (int i = 0; i < num_vertices; i++) { for (int j = 0; j < num_vertices; j++) { graph[i][j] = 0; } visited[i] = false; } // 读取边的信息 printf("请输入边的信息(起点 终点):\n"); for (int i = 0; i < num_edges; i++) { int start, end; scanf("%d %d", &start, &end); graph[start][end] = 1; graph[end][start] = 1; // 若是无向图,需要设置对称的边 } int start_vertex; printf("请输入起始顶点:"); scanf("%d", &start_vertex); printf("深度优先搜索结果:"); DFS(start_vertex, num_vertices); return 0; } ``` 广度优先搜索(BFS)是一种用于遍历或搜索树或图的算法。它从根节点开始,逐层地访问节点,先访问当前层的所有节点,然后再访问下一层的节点。BFS可以使用队列来实现。 以下是C语言实现广度优先搜索的示例代码: ```c #include <stdio.h> #include <stdbool.h> #define MAX_SIZE 100 // 图的邻接矩阵表示 int graph[MAX_SIZE][MAX_SIZE]; bool visited[MAX_SIZE]; // 记录节点是否被访问过 // 广度优先搜索函数 void BFS(int start_vertex, int num_vertices) { int queue[MAX_SIZE]; int front = 0, rear = 0; visited[start_vertex] = true; printf("%d ", start_vertex); queue[rear++] = start_vertex; while (front < rear) { int vertex = queue[front++]; for (int i = 0; i < num_vertices; i++) { if (graph[vertex][i] && !visited[i]) { visited[i] = true; printf("%d ", i); queue[rear++] = i; } } } } int main() { int num_vertices, num_edges; printf("请输入图的顶点数和边数:"); scanf("%d %d", &num_vertices, &num_edges); // 初始化图的邻接矩阵 for (int i = 0; i < num_vertices; i++) { for (int j = 0; j < num_vertices; j++) { graph[i][j] = 0; } visited[i] = false; } // 读取边的信息 printf("请输入边的信息(起点 终点):\n"); for (int i = 0; i < num_edges; i++) { int start, end; scanf("%d %d", &start, &end); graph[start][end] = 1; graph[end][start] = 1; // 若是无向图,需要设置对称的边 } int start_vertex; printf("请输入起始顶点:"); scanf("%d", &start_vertex); printf("广度优先搜索结果:"); BFS(start_vertex, num_vertices); return 0; } ``` 希望对你有所帮助!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值