图的遍历(graph traversal)
1.给出一个图G和其中任意一个顶点V0,从V0出发系统地访问G中所有的顶点,每个顶点访问而且只访问一次。
2.从一个顶点出发,试探性访问其余顶点,同时必须考虑到下列情况
- 从一顶点出发,可能不能到达所有其他的顶点,如非连通图
- 也可能会陷入死循环,如存在回路的图
3.解决方法:为每个顶点保留一个标志位, 算法开始时,所有顶点的标志位置零,在遍历的过程中,当某个顶点被访问时,其标志位就标记为已访问
深度优先遍历(depth-first search)
1.深搜(简称DFS)类似于树的先根次序遍历,尽可能先对纵深方向进行搜索
2.选取一个未访问的点v0作为源点
- 访问顶点v0
- 递归地深搜遍历v0邻接到的其他顶点
- 重复上述过程直至从v0有路径可达的顶点都已被访问过
3.再选取其他未访问顶点作为源点做深搜,直到图的所有顶点都被访问
图的深度优先遍历(DFS)算法
void DFS(Graph& G,int v) //深度优先搜索的递归实现
{
G.Mark[v]=VISITED; //把标记位设置位VISITED
Visit(G,v); //访问顶点v
for(Edge e=G.FirstEdge(v);G.IsEdge(e);e=G.NextEdge(e))
if(G.Mark[G.ToVertex(e]==UNVISITED)
DFS(G,G.ToVertex(e));
PostVisit(G,v); //对顶点v的后访问
}
广度优先遍历(breadth-first search)
1.广度优先搜索(BFS),遍历过程:
- 从图中的某个顶点v0出发
- 访问并标记顶点v0
- 一层层横向搜索v0的所有邻接点
- 对这些邻接点一层层横向搜索,直至所有由v0有路径可达的顶点都已被访问过
- 再选取其他问访问的顶点作为源点做广搜,直到所有点都被访问
BFS算法
void BFS(Graph& G,int v)
{
using std::queue;
queue<int>Q; //使用STL中的队列
Visit(G,v); //访问顶点v
G.Mark[v]=VISITED; //标记
Q.push(v); //入队列
while(!Q.empty()) //如果队列非空
{
int u=Q.front(); //获取队列顶部元素
Q.pop(); //队列顶部元素出队
for(Edge e=G.First(u);G.IsEdge(e);e=G.NextEdge(e)) //所有未访问的邻接点入队
if(G.Mark[G.ToVertex(e)]==UNVISITED)
{
Visit(G,G.ToVertex(e));
G.Mark[G.ToVertex(e)]=VISITED;
Q.push(G.ToVertex(e));
}
}
}
拓扑排序
1.对于有向无环图G=(V,E),V里顶点的线性序列称作一个拓扑序列,该顶点序列满足:
- 若在有向无环图G中从顶点vi到 vj有一条路径,则在序列中顶点vi必在vj之前
2.拓扑排序
-将一个有向无环图中所有顶点在不违反先决条件关系的前提下排成线性序列的过程称为拓扑排序
拓扑排序方法
1.任何有向无环图,其顶点都可以排在一个拓扑序列里,其拓扑排序的方法是:
- 1.从图中选择任意一个入度为0的顶点且输出之
- 2.从图中删掉此顶点及其所有的出边,将其入度减少1
- 3.回到第1步继续执行