图的深度遍历和广度遍历(java实现)

9 篇文章 0 订阅
6 篇文章 0 订阅

在说图的广度遍历和深度遍历之前,我们可以回想下,树的先序遍历和层次遍历,先序遍历我们是不是从根节点一直递归到叶子节点,然后再慢慢回退,图的深度遍历也是类似的。

图的深度遍历,只需要额外一个数组记录顶点是否有访问过,下面就使用矩阵来实现图,和图的深度遍历。
//这里n为顶点的数量
private boolean[] isVisited = new boolean[n];
//这里为矩阵构建的图1为边
private int[][] edges;
public void dfs(int n){
	//这里打印对应的索引
	System.out.print(n);
	//打印说明当前节点已经访问了,我们改变他的状态
	isVisited[n] = true;
	//现在寻找当前节点连接的相邻节点
	int w = getFirstNeigphbor(n);
	//只要找到了节点,我们就递归访问
	while(w != -1){
		//如果相邻的节点没有被访问过,我们就递归调用相邻节点
		if(!isVisited[w]){
			dfs(n);
		}
		//访问完我们就接着访问,当前节点的相邻节点的下一个相邻节点
		w = getNextNeigphbor(n, w);
	}
}
//获取当前节点的第一个相邻节点
//edges:我们的存储顶点的矩阵
//n:每一个索引都代表一个顶点
public void getFirstNeigphbor(int n){
	int[] edge = edges[n];
	for(int i = 1; i < edge.length; i++) {
		//我们用1代表两个点的边
		if(edge[i] == 1){
			return i;
		}
	}
	//没有找到我们返回-1
	return -1;
}
//获取当前节点的相邻节点的下一个相邻节点
//n:当前节点
//w:相邻节点
public void getFirstNeigphbor(int n, int w){
	int[] edge = edges[n];
	for(int i = w + 1; i < edge.length; i++) {
		//我们用1代表两个点的边
		if(edge[i] == 1){
			return i;
		}
	}
	//没有找到我们返回-1
	return -1;
}

这里就只给出了深度遍历的必要的几个方法,基本的图数据结构自己可以实现下,如果是不连通图,我们可以再加一个循环,依次遍历每一个顶点,这里就是简单的实现,也没有啥优化,等以后我学了优化再来补吧。

下面就是广度遍历了,先介绍它的基本思想吧,它和树的层次遍历很相似,也是使用队列的特性,把初始节点添加进去,当元素出队列的时候我们就需要把它相邻的节点依次入队,和上面一样我们还需要记录当前节点是否访问过。

public void bfs(int n) {
	//创建一个队列
	LinkedList<Integer> queue = new LinkedList();
	queue.add(n)
	//辅助数组我们就用刚刚上面哪个isVisited;
	//只要元素入队了,我们就改变它的标记
	isVisited[n] = true;
	//只要队列不空,我们就一直循环
	while(queue.size() > 0) {
		//取出队列元素
		int i = queue.removeFirst();
		System.out.print(i);
		//获取队列想连接的第一个顶点,我们还是使用上面的方法
		int w = getFirstNeigphbor(i);
		while(w != -1) {
			//没有访问我们就入队
			if(!isVisited[w]) {
				queue.add(w);
			}
			//访问了我们就取下一个相邻的顶点
			w = getNextNeigphbor(i, w);
		}
	}
}
到此图的深度和广度遍历结束了,后面将会写普利姆算法和克鲁斯卡尔算法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值