广度优先遍历BFS:
举个例子,先找到A点访问,然后访问A的所有邻居B,C,然后访问B的所有邻居,C的所有邻居(邻居是指相联通的点),所以访问顺序是同一级的一起访问,所以可以类比树的层序遍历。
思路及实现:
#include <iostream>
#include <queue>
#include <vector>
#define INFINITY 9
#define DISCOVER 1
#define UNDISCOVERED 0
#define VISITED 2
using namespace std;
int i = 1;
struct node{
int index;
int status;
node() :index(i++), status(UNDISCOVERED){}
};
vector<node> nodes(6);//定点集
int& status(int i){
return nodes[i].status;
}
int map[6][6] = {//边的二维表
{0,1,1,0,0,0},
{1,0,0,1,0,0},
{1,0,0,1,0,0},
{0,1,1,0,1,0},
{0,0,0,1,0,1},
{0,0,0,0,1,0}
};
int getNextSib(int i, int j){//返回下一个孩子的下标
while (-1 < j--){
if (map[i][j] != 0){
return j;
}
}
return j;
}
void bfs(int v){
queue<int> q;
q.push(v);
status(v) = DISCOVER;//记录首节点
while (!q.empty()){
int currentNode = q.front();//推出被访问的节点
q.pop();
//找到并保存该节点所有没有被访问过的相邻节点
for (int i = getNextSib(currentNode, 6); -1 < i; i = getNextSib(currentNode, i)){
if (status(i) == UNDISCOVERED){//如果该节点未被发现过
status(i) = DISCOVER;
q.push(i);//加入队列等待访问
}
//其他的状态都不用添加
}
if (status(currentNode) == DISCOVER){
cout << nodes[currentNode].index << endl;//进行访问
status(currentNode) = VISITED;
}
}
}
一个结论:在这样一个图(每条边没有权重)遍历的过程中得到的支撑树中每个节点的深度即为该点到起点的最短路径。
深度优先遍历DFS:
过程大致如下:
- 访问顶点s
- 若s存在没有访问过的相邻的顶点,那么在s的所有未被访问过的邻居中,任选其一u,递归执行DFS(u)
- 如果s不存在没有访问过的相邻顶点,那么一直向上回溯到存在未访问过相邻顶点的节点,直至根节点也不再有未访问过的相邻节点
一个结论:在DFS结束后,可以根据每个节点的dTime和fTime这个区间是否是另一个节点时间区间的子集来判断是否有直系关系。