图-深度优先搜索和广度优先搜索

深度优先搜索(Depth First Search, DFS)

深度优先遍历图的方法是,从图中某顶点v出发:

(1)访问顶点v;

(2)依次从v的未被访问的邻接点出发,对图进行深度优先遍历;直至图中和v有路径相通的顶点都被访问;

(3)若此时图中尚有顶点未被访问,则从一个未被访问的顶点出发,重新进行深度优先遍历,直到图中所有顶点均被访问过为止。

可以看到这里面运用了递归的思想,下面给出了DFS算法基于邻接矩阵与邻接表的不同算法。对于基于邻接矩阵的算法,由于其是一个二维数组,要查找每个顶点的邻接点需要访问矩阵中的所有元素,因此其时间复杂度为O(n^2),而基于邻接表的DFS算法的时间复杂度则为O(n+e)。

基于邻接矩阵的DFS算法实现:

#include "邻接矩阵.h"
#define TRUE 1
#define FALSE 0
typedef int Boolean;
Boolean visited[MAXVEX];
void DFS(MGraph G, int i) {
	int j;
	visited[i] = TRUE;
	printf("%c", G.vexs[i]); /*输出访问顶点*/
	for(j = 0; j < G.numVertexes; j++){
		if(G.vexs[i][j] >= 1 && !visited[j]){
			/*为什么是>=1?因为可能是网,带有权值*/
			/*倘若(vi,vj)有边而且顶点j未被访问过则:*/
			DFS(G, j);
		}
	}
}
void DFSTraverse(MGraph G){
	int i;
	/*初始化visited数组,置所有顶点访问状态为FALSE*/
	for(i = 0; i < G.numVertexes; i++){
		visited[i] = FALSE;
	}
	for(i = 0; i < G.numVertexes; i++){
		/*对应连通图,这个循环只会执行一次,对于非连通图执行的次数为连通分量的个数,循环直到所有顶点都被访问。*/
		if(!visited[i]){
			DFS(G, i);
		}
	}
}

基于邻接表的DFS算法实现:

#include "邻接表.h"
#define TRUE 1
#define FALSE 0
typedef int Boolean;
Boolean visited[MAXVEX];
void DFS(GraphAdjList G, int i){
	EdgeNode * e;
	visited[i] = TRUE;
	printf("%c", G->adjList[i].data);
	e = G->adjList[i].firstEdge;
	while(e){
		if(!visited[e->adjVex]){
			DFS(G, e->adjVex);
		}
		e = e->next;
	}
}
void DFSTraverse(GraphAdjList G){
	int i;
	/*初始化visited数组,置所有顶点访问状态为FALSE*/
	for(i = 0; i < G->numVertexes; i++){
		visited[i] = FALSE;
	}
	for(i = 0; i < G->numVertexes; i++){
		/*对应连通图,这个循环只会执行一次,对于非连通图执行的次数为连通分量的个数,循环直到所有顶点都被访问。*/
		if(!visited[i]){
			DFS(G, i);
		}
	}
}

广度优先搜索(Breadth First Search, BFS)

1、把根节点放到队列的末尾。

2、每次从队列的头部取出一个元素,查看这个元素所有的下一级元素,把它们放到队列的末尾。并把这个元素记为它下一级元素的前驱。

3、找到所要找的元素时结束程序。

4、如果遍历整个树还没有找到,结束程序。 [1]

基于邻接矩阵的BFS算法实现:

#include "邻接矩阵.h"
#define TRUE 1
#define FALSE 0
typedef int Boolean;
Boolean visited[MAXVEX];
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]){
			visited[i] = TRUE;
			printf("%c", G.vexs[i]);
			Enqueue(&Q, i);
			while(!QueueEmpty(Q)){
				Dequeue(&Q, &i);/*队首出队赋给i*/
				/*判断其他所有顶点若与当前顶点存在边且未访问过*/
				for(j = 0; j < G.numVertexes; j++){
					if(G.arc[i][j] >= 1 && visited[j]){
						visited[j] = TRUE;
						printf("%c", G.vexs[j]);
						Enqueue(&Q, j);
					}
				}
			}
		}
	}
}

基于邻接表的BFS算法实现:

#include "邻接表.h"
#define TRUE 1
#define FALSE 0
typedef int Boolean;
Boolean visited[MAXVEX];
void BFSTraverse(GraphAdjList G, int i){
	EdgeNode * e;
	int i;
	Queue Q;
	for(i = 0; i < G->numVertexes; i++){
		visited[i] = FALSE;
	}
	InitQueue(&Q);
	for(i = 0; i < G->numVertexes; i++){
		if(!visited[i]){
			visited[i] = TRUE;
			printf("%c", G->adjList[i].data);
			Enqueue(&Q, i);
			while(!QueueEmpty(Q)){
				Dequeue(&Q, &i);
				e = G->adjList[i].firstEdge;
				while(e){
					if(!visited[e->adjvex]){
						visited[e->adjvex] = TRUE;
						printf("%c", G->adjList[e->adjvex].data);
						Enqueue(&Q, e->adjvex);/*将此顶点入队*/
					}
					p = p->next;/*指向下一个邻接点*/
				}
			}
		}
	}
}

DFS BFS两者的区别举例说明

假设我们要在家里找某一样找不到的东西,我们会有很多种寻找的方案,如果我们采用深度优先搜索,就可以这样去理解:先到卧室,寻找柜子,再寻找搜索柜子里的抽屉,再寻找抽屉里的收纳盒。。。以此类推直到我们已经寻遍卧室的每一个角落。再去搜索书房。。。就类似于树的前序遍历。而对于广度优先算法我们可以这样理解:第一轮先搜索卧室的柜子、书房的柜子、客厅的柜子,第二轮寻找卧室的柜子里的抽屉、书房的柜子的抽屉、客厅的柜子的抽屉。。。以此类推。和树的层序遍历很相似。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值