图的广度优先历遍和深度优先历遍

今天介绍图(森林)的深度优先历遍和广度优先历遍

1、以下算法是用java实现的,但核心的步骤跟C语言差不多,先介绍必要的数据结构

1.1、图(当取定图中某个顶点为树根时,可依次把图划分为一棵树或若干棵树即森林

import java.util.ArrayList;
/*
 * 图的数据结构,由顶点数组和图的类型组成
 */
public class Graph
{
	ArrayList<Point> points = new ArrayList(); //顶点数组
	String graphKind; //图的类型,此处没用到,一概假定为无向图
	
	//添加顶点
	public void addPoint(Point p){
		points.add(p);
	}
	
	//移除顶点,连与顶点有关的边都移除
	public void removePoint(Point removePoint){
		for(Point p : points)
			for(AdjacentEdge edge : p.adjcentEdges){
				if(edge.adjacentPointIndex == removePoint.pointIndex)
					p.adjcentEdges.remove(edge);
					
		}
		
		points.remove(removePoint);
	}
}
1.2、点

import java.util.LinkedList;
/*
 * 点的数据结构
 */
public class Point
{
	boolean isVisited = false; //该点是否被访问过
	int pointIndex; //点的下标
	String data;  //点代表的数据
	LinkedList<AdjacentEdge> adjcentEdges = new LinkedList(); //点的邻接边数组
	
	public Point(int pointIndex, String data){
		this.pointIndex = pointIndex;
		this.data = data;
	}
	
	//添加邻接边
	public void addAdjacentEdge(AdjacentEdge adjacentEdge){
		adjcentEdges.add(adjacentEdge);
	}
	
	//删除邻接边
	public void removeAdjacentEdge(AdjacentEdge adjacentEdge){
		adjcentEdges.remove(adjacentEdge);
	}
	
	@Override
	public String toString()
	{
		// TODO Auto-generated method stub
		return "[" + pointIndex + "]" + data + "  ";
	}
}
1.3、邻接边

/*
 * 此类代表邻接边的信息
 */
public class AdjacentEdge
{
	int adjacentPointIndex; //邻接边顶点的编号,此处的编号是顶点数组中对应的下标
	int edgeInfo;//邻接边的信息,即权值,若无则为0
	
	public AdjacentEdge(int adjacentPointIndex,int edgeInfo){
		this.adjacentPointIndex = adjacentPointIndex;
		this.edgeInfo = edgeInfo;
	}
	
	public AdjacentEdge(int adjacentPointIndex){
		this(adjacentPointIndex, 0);
	}
}

2、深度优先历遍

2.1、思路:

1)假定图的顶点数组中某顶点(第一次假定为第一个顶点)为树的根,进行访问

2)访问点后,看点是否有邻接边,有则对每一邻接边进行递归深度优先历遍

3)查看顶点数组中有没有没被访问的顶点,若有,则返回

2.2、算法实现:

public class DepthFirstSerch
{
 /* 采用递归的思想 */	
	
	//对图中某个点的访问
	public static void dfsOne(Graph graph, Point startPoint){
		System.out.print(startPoint);
		startPoint.isVisited = true;
		
		//访问顶点有无邻接边,有则进行递归,深度优先的思想,一直深入到尽头
		for(AdjacentEdge edge : startPoint.adjcentEdges)
			if(!graph.points.get(edge.adjacentPointIndex).isVisited)
				dfsOne(graph, graph.points.get(edge.adjacentPointIndex));
	}
	
	//对整个图进行深度优先历遍,对没访问过的结点逐一进行深度历遍
	public static void dfsAll(Graph graph){
		for(Point p : graph.points)
			if(!p.isVisited)
				dfsOne(graph, p);
	}
	
	//测试算法正确性
	public static void main(String[] args){
		Graph graph = new Graph(); //创建图
		//初始化顶点数组
		for(int i = 0 ; i < 10 ; i++){
			graph.addPoint(new Point(i, "point" + i));
		}
		
		//给顶点添加邻接边
		graph.points.get(0).addAdjacentEdge(new AdjacentEdge(1));
		graph.points.get(0).addAdjacentEdge(new AdjacentEdge(2));
		graph.points.get(1).addAdjacentEdge(new AdjacentEdge(3));
		graph.points.get(3).addAdjacentEdge(new AdjacentEdge(4));
		graph.points.get(2).addAdjacentEdge(new AdjacentEdge(5));
		
		//进行深度优先历遍
		dfsAll(graph);
	}
}


3、广度优先历遍
3.1、思路:

1)假定图的顶点数组中某顶点(第一次假定为第一个顶点)为树的根,该顶点未被访问,则访问后入队

2)从队列中出队一个顶点进行访问,有邻接边则且邻接边顶点未被访问,则对邻接顶点逐一访问(不递归),并按序入队

3)查看顶点数组中有没有没被访问的顶点,若有,则返回 1)

3.2、算法实现:

import java.util.LinkedList;
import java.util.Queue;

/*
 * 广度优先历遍
 */
public class BreadthFirstSearch
{
	//广度优先历遍步骤:从队列中出队一个顶点进行访问,有邻接边则对邻接边顶点逐一访问(不递归),并按序入队
	public static void bfs(Graph graph){
		Queue<Point> queue = new LinkedList<Point>(); //定义顶点队列 
		Point temp; //队列出队顶点
		for(Point p : graph.points){
			//若顶点未被访问,则访问并入队
			if(!p.isVisited){
				System.out.print(p);
				p.isVisited = true;
				queue.offer(p); //入队
			}
			//对出队顶点进行邻接顶点的访问,有未被访问到的则访问并入队
			while((temp = queue.poll()) != null)
				for(AdjacentEdge edge : temp.adjcentEdges){
					Point adjacentPoint = graph.points.get(edge.adjacentPointIndex);
					if(!adjacentPoint.isVisited){
						System.out.print(adjacentPoint);
						adjacentPoint.isVisited = true;
						queue.offer(adjacentPoint); //入队
					}
				}
		}
	}
	
	//对算法进行测试
	public static void main(String[] args){
		Graph graph = new Graph(); //初始化图
		//初始化图的顶点数组
		for(int i = 0 ; i < 10 ; i++){
			graph.addPoint(new Point(i, "point" + i));
		}
		
		//为顶点添加邻接边
		graph.points.get(0).addAdjacentEdge(new AdjacentEdge(9));
		graph.points.get(0).addAdjacentEdge(new AdjacentEdge(2));
		graph.points.get(9).addAdjacentEdge(new AdjacentEdge(3));
		graph.points.get(3).addAdjacentEdge(new AdjacentEdge(4));
		graph.points.get(2).addAdjacentEdge(new AdjacentEdge(5));
		
		//广度优先历遍
		bfs(graph);
	}
}



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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值