Java-图的遍历模式

图遍历介绍

所谓图的遍历,即是对节点的访问,一个图有那么多节点,如何遍历这些节点,需要特定策略,一般有两种访问策略:1.深度优先遍历2.广度优先遍历

深度优先遍历基本思想

1.深度优先遍历,从初始访问节点出发,初始访问节点可能有很多邻接节点,深度优先遍历的策略就是首先访问第一个邻接节点,然后再以这个被访问的邻接节点作为初始节点,访问它的第一个邻接节点,可以这样理解,每次都在访问完当前节点后首先访问当前节点的第一个邻接节点
2.我们可以看到,这样的访问策略是优先往纵向深入挖掘,而不是对一个节点的所有邻接节点进行横向访问
3.显然,深度优先搜索是一个递归的过程

深度优先遍历算法步骤

1.访问初始节点v,并标记节点v已访问
2.查找节点v的第一个邻接节点w
3.若w存在,则继续执行4,若w不存在,则回到第一步,将从v的下一个节点继续
4.若w未被访问,对w进行深度优先递归遍历(即把w当作一个v,然后进行步骤123)
5.查找v的w邻接节点的下一个邻接节点,转到步骤3

代码实现
//得到一个邻接节点下标w
	public int getFirstNeighbor(int index) {
		for(int j=0;j<vertexList.size();j++) {
			if(edges[index][j]>0) {
				return j;
			}
		}
		return -1;
	}
	//根据前一个邻接节点的下标来获取下一个邻接节点
	public int getNextNeighbor(int v1,int v2) {
		for(int j=v2+1;j<vertexList.size();j++) {
			if(edges[v1][j]>0) {
				return j;
			}
		}
		return -1;
	}
	//深度优先遍历算法
	//i第一次就是0
	public void dfs(boolean[] isVisited,int i) {
		//首先我们访问该节点,输出
		System.out.println(getValueByIndex(i)+"->");
		//将节点设置为已访问
		isVisited[i]=true;
		//查找节点i的第一个邻接节点w
		int w=getFirstNeighbor(i);
		while(w!=-1) {//说明有
			if(!isVisited[w]) {
				dfs(isVisited,w);
			}
			//如果w节点已经被访问过
			w=getNextNeighbor(i, w);
		}
	}
	//对dfs进行重载,遍历我们所有的节点,并进行dfs
	public void dfs() {
		//对所有的节点进行dfs
		for(int i=0;i<getNumOfVertex();i++) {
			if(!isVisited[i]) {
				dfs(isVisited,i);
			}
		}
	}

广度优先遍历基本思想

图的广度优先搜索类似于一个分层搜索的过程,广度优先遍历需要使用一个队列以保持访问过的节点顺序,以便按这个顺序来访问这些节点的邻接节点

广度优先遍历算法步骤

1.访问初始节点v并标记v已访问
2.节点v入队列
3.当队列非空时继续执行,否则算法结束
4.出队列,取得队头结点u
5.查找节点u的第一个邻接节点w
6.若节点u的邻接节点w不存在,则转到3,否则继续执行下面三个步骤
6.1若节点w尚未访问,则访问节点w并标记为已访问
6.2节点w入队列
6.3查找节点u的继w邻接节点后的下一个邻接节点w,转到6

代码实现
// 广度优先遍历
	public void bfs(boolean[] isVisited, int i) {
		int u;// 表示队列头节点的下标
		int w;// 邻接节点w
		// 队列,记录节点的访问顺序
		LinkedList queue = new LinkedList();
		// 访问节点,输出节点信息
		System.out.println(getValueByIndex(i));
		// 标记为已访问
		isVisited[i] = true;
		// 将节点加入队列
		queue.addLast(i);
		while (!queue.isEmpty()) {
			// 取出队列的头节点下标
			u = (Integer) queue.removeFirst();
			// 得到第一个邻接节点的下标w
			w = getFirstNeighbor(u);
			while (w != -1) {
				// 是否访问过
				if (!isVisited[w]) {
					System.out.println(getValueByIndex(w));

					// 标记为已访问
					isVisited[w] = true;
					// 入队
					queue.addLast(w);
				}
				// 以u为前驱点,找w后面的下一个邻接点
				w = getNextNeighbor(u, w);
			}

		}
	}

	// 重载bfs,考虑有不连通节点的情况
	public void bfs() {
		isVisited = new boolean[vertexList.size()];
		for (int i = 0; i < getNumOfVertex(); i++) {
			if (!isVisited[i]) {
				bfs(isVisited, i);
			}
		}
	}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值