提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
深度优先遍历:深度优先遍历是图论中的经典算法。其利用了深度优先搜索算法可以产生目标图的相应拓扑排序表,采用拓扑排序表可以解决很多相关的图论问题,如最大路径问题等等。
广度优先遍历:广度优先遍历是连通图的一种遍历策略,因为它的思想是从一个顶点V0开始,辐射状地优先遍历其周围较广的区域故得名。
深度优先遍历结果:1 2 4 5 3 6 7,广度优先遍历结果:1 2 3 4 5 6 7
一、深度优先遍历
思想:
- 从一个未被访问过的顶点开始,沿着它的边访问它的邻接顶点,如果邻接顶点还有未被访问过的邻接顶点,就继续访问,直到所有邻接顶点都被访问过为止。
- 如果还有其他未被访问过的顶点,就从其中一个顶点重新开始,重复上述过程,直到所有顶点都被访问过为止。
1、邻接矩阵存储,且用递归实现:
#define MAXVBA 100
#define INFINITY 65536
typedef struct {
char vexs[MAXVBA];
int arc[MAXVBA][MAXVBA];
int numVertexes, numEdges;
} MGraph;
// 邻接矩阵的深度有限递归算法
#define TRUE 1
#define FALSE 0
#define MAX 256
typedef int Boolean; // 这里我们定义Boolean为布尔类型,其值为TRUE或FALSE
Boolean visited[MAX]; // 访问标志的数组
void DFS(MGraph G, int i){
visited[i] = TRUE;
printf("%c", G.vexs[i]);
for (int j = 0; j < G.numVertexes; ++j) {
if (G.arc[i][j] == 1 && !visited[j]){
DFS(G, j); // 对为访问的邻接顶点递归调用
}
}
}
// 邻接矩阵的深度遍历操作
void DFSTraverse(MGraph G){
int i;
// 初始化所有顶点状态都是未访问过状态
for (i = 0; i < G.numVertexes; ++i) {
visited[i] = FALSE;
}
//防止图为非联通的情况,遍历整个图
for (i = 0; i < G.numVertexes; ++i) {
if (!visited[i]){ // 若是连通图,只会执行一次
DFS(G, i);
}
}
}
2、邻接矩阵存储,且用栈实现:
void DFS_Stack(MGraph G, int i)
{
int node;
int count = 1;
printf("%c ", G.vexs[i]); // 打印已访问顶点
visited[i] = TRUE;
node = i;
push(i); //开始的节点入栈
while(count < G.numVertexes) //still has node not visited
{
/* 所有被访问的节点依次入栈,只有node当找不到下一个相连的节点时,才使用出栈节点 */
for(j=0; j < G.numVertexes; j++)
{
if(G.arc[node][j] == 1 && visited[j] == FALSE)
{
visited[j] = TRUE;
printf("%c ", G.vexs[j]);
count++;
push(j); //push node j
break;
}
}
if(j == G.numVertexes) //与node相连的顶点均已被访问过,所以需要从stack里取出node的上一个顶点,再看该顶点的邻接顶点是否未被访问
node = pop();
else //找到与node相连并且未被访问的顶点,
node = j;
}
}
3、邻接表存储:
// 邻接表的深度有限递归算法
#define TRUE 1
#define FALSE 0
#define MAX 256
typedef int Boolean; // 这里我们定义Boolean为布尔类型,其值为TRUE或FALSE
Boolean visited[MAX]; // 访问标志的数组
void DFS(GraphAdjList GL, int i)
{
EdgeNode *p;
visited[i] = TRUE;
printf("%c " GL->adjList[i].data);
p = GL->adjList[i].firstEdge;
while(p)
{
if( !visited[p->adjvex] )
{
DFS(GL, p->adjvex);
}
p = p->next;
}
}
// 邻接表的深度遍历操作
void DFSTraverse(GraphAdjList GL)
{
int i;
for( i=0; i < GL->numVertexes; i++ )
{
visited[i] = FALSE; // 初始化所有顶点状态都是未访问过状态
}
for( i=0; i < GL->numVertexes; i++ )
{
if( !visited[i] ) // 若是连通图,只会执行一次
{
DFS(GL, i);
}
}
}
二、广度优先遍历
思想:
- 从一个未被访问过的顶点开始,按照一定的顺序访问它的所有邻接顶点,然后再按照相同的顺序访问这些邻接顶点的所有未被访问过的邻接顶点,直到所有顶点都被访问过为止。
- 广度优先遍历类似于层次遍历,每次先访问距离起始顶点最近的顶点,然后再访问距离起始顶点次近的顶点,依次类推,直到访问到最远的顶点。
// 邻接矩阵的广度遍历算法
void BFSTraverse(MGraph G)
{
int i, j;
Queue Q;
for( i=0; i < G.numVertexes; i++ )
{
visited[i] = FALSE;
}
initQueue( &Q );
for( i=0; i < G.numVertexes; i++ )
{
if( !visited[i] )
{
printf("%c ", G.vex[i]);
visited[i] = TRUE;
EnQueue(&Q, i);
while( !QueueEmpty(Q) )
{
DeQueue(&Q, &i);
for( j=0; j < G.numVertexes; j++ )
{
if( G.art[i][j]==1 && !visited[j] )
{
printf("%c ", G.vex[j]);
visited[j] = TRUE;
EnQueue(&Q, j);
}
}
}
}
}
}