图的遍历方式 深度优先&&广度优先

恰巧离散数学学到了图的矩阵表示(最后一节了),复习一下图的遍历方式吧,没想到网课上到了将近结课

一、举例分析

深度优先搜索(DFS)是一种顺序搜索,一条路走到黑,直到搜索无法进行,回退到上一个可继续搜索的点,逐渐遍历全图。
广度优先搜索(BFS)将图分离为层,每层之间间隔一步,每个点被遍历的次序和遍历该图的初始点的距离有关。
在这里插入图片描述
如该图例子1,按照深度优先搜索从点1开始遍历:

  1. 1–>2–>4,无法继续搜索,回退一步到点2
  2. 2–>5,无法继续搜索,回退一步到点2
  3. 仍然无法继续,再回退一步到起点1
  4. 1–>3,已搜索完全部点,搜索结束
  5. 遍历顺序为1–>2–>4–>5–>3,总结就是一条路走到黑,然后回头走这条路上的分支

按照广度优先搜索从点1开始遍历:

  1. 点1可以到达点2和点3,当前已遍历1–>2–>3
  2. 点2可以到达点4和点5,当前已遍历1–>2–>3–>4–>5;点3无法继续
  3. 点4和点5均无法继续,搜索结束,遍历顺序为1–>2–>3–>4–>5
  4. 总结就是将图分为层,每次通过该层的点确定下一层的点,如此直到搜索到最后一层

再举个例子2,分析一下广度优先搜索
在这里插入图片描述
深度优先搜索该图,一条路走到黑刚好遍历完全,1–>2–>3–>4–>5–>6–>7–>8
按照广度优先搜索,从点1开始遍历:

  1. 点1可以到达2,当前已遍历1–>2
  2. 点2可到达点3和点7,当前已遍历1–>2–>3–>7
  3. 点3可到达点4,当前已遍历1–>2–>3–>7–>4;点7可到达点5和点6,当前已遍历1–>2–>3–>7–>4–>5–>6
  4. 点4、点5和点6均不符合继续搜索的条件,搜索结束,遍历顺序为1–>2–>3–>7–>4–>5–>6
  5. 这就是把图分为了4层({1},{2},{3,7},{4,5,6}),由上一层确定下一层的点,不重复遍历

二、写成代码

用邻接矩阵表示图,

1.深度优先
可以用递归模拟一条路走到黑,走到黑屋后return返回到上一个仍可继续搜索的地方

#include <iostream>
#include <stdio.h>
#include <string>
#include <algorithm>

using namespace std;

int My_Map[21][21] = {
    
     0 }, book[21] = {
    
     0 };//book标记,0该店未遍历,1已遍历
int n, sum = 0;

void dfs(int step) {
    
    //当前处于编号为step的点
	cout << step << " ";
	sum++;
	if (sum == n) return;//已遍历完所有点
	for (int i = 1; i <= n; i++) {
    
    
		if (My_Map[step][i] == 1 && book[i] == 0) {
    
    
			book[i] = 1;
			dfs(i);//继续走,直到黑屋再回来
		}
	}
	return;
}

int main() {
    
    
	cout << "输入邻接矩阵行列数:";
	cin >> n;
	cout << "输入邻接矩阵:" << endl;
	for (int a = 1; a <= n; a++) {
    
    
		for (int b = 1; b <= n; b++) {
    
    
			cin >> My_Map[a][b];
		}
	}
	book[1] = 1;
	cout << "DFS遍历顺序为:";
	dfs(1);
	return 0;
}

例1的测试:
在这里插入图片描述

2.广度优先
根据上一层的点确定下层的点,且越早找到的点被用来作为确定下一层点的时机越早,利用队列先进先出的特性

#include <iostream>
#include <stdio.h>
#include <string>
#include <algorithm>
#include <queue>

using namespace std;

int main() {
    
    
	int n;
	cout << "输入邻接矩阵行列数:";
	cin >> n;
	cout << "输入邻接矩阵:" << endl;
	int My_Map[21][21], book[21] = {
    
     0 };
	for (int a = 1; a <= n; a++) {
    
    
		for (int b = 1; b <= n; b++) {
    
    
			cin >> My_Map[a][b];
		}
	}
	queue<int> que;//队列中存储待遍历的点
	que.push(1);//从1号开始遍历
	book[1] = 1;
	cout << "BFS遍历顺序为:";
	while (!que.empty()) {
    
    
		cout << que.front() << " ";
		for (int i = 1; i <= n; i++) {
    
    
			if (My_Map[que.front()][i] == 1 && book[i] == 0) {
    
    
				que.push(i);
				book[i] = 1;
			}
		}
		que.pop();
	}
	cout << endl;
	return 0;
}

例2的测试:
在这里插入图片描述
其实这两个图是我在离散的课本上随便抠出来的(lll¬ω¬)

猜你喜欢

转载自blog.csdn.net/ccmtvv/article/details/106085112