图的广度优先历遍和深度优先历遍
2016-04-16 08:49
281 查看
今天介绍图(森林)的深度优先历遍和广度优先历遍
1、以下算法是用java实现的,但核心的步骤跟C语言差不多,先介绍必要的数据结构
1.1、图(当取定图中某个顶点为树根时,可依次把图划分为一棵树或若干棵树即森林
2、深度优先历遍
2.1、思路:
1)假定图的顶点数组中某顶点(第一次假定为第一个顶点)为树的根,进行访问
2)访问点后,看点是否有邻接边,有则对每一邻接边进行递归深度优先历遍
3)查看顶点数组中有没有没被访问的顶点,若有,则返回
2.2、算法实现:
3、广度优先历遍
3.1、思路:
1)假定图的顶点数组中某顶点(第一次假定为第一个顶点)为树的根,该顶点未被访问,则访问后入队
2)从队列中出队一个顶点进行访问,有邻接边则且邻接边顶点未被访问,则对邻接顶点逐一访问(不递归),并按序入队
3)查看顶点数组中有没有没被访问的顶点,若有,则返回 1)
3.2、算法实现:
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); } }
相关文章推荐
- poj 1239 Increasing Sequences dp lis
- STM32——DMA
- Android的资源功能篇
- Kafka设计解析(一)- Kafka背景及架构介绍
- python-递归函数.汉诺塔.
- linux杂谈
- ReactMix框架是基于ReactNative框架实现的,目标是完全兼容现有的H5开发方式的新一代框架ReactMix
- 智能进化论
- 用C语言创建文件写入并读取
- NDCG Normalized discounted cumulative gain 理解分析
- qt输入框
- 通过下标全选反选,删除
- 【笔试/面试】—— 不使用大于、小于、if 语句,实现 max 宏
- 2016.4.16 随想
- UI中一些不常用的控件UIActivityIndicatorView、UIProgressView、UISegmentedControl、UIStepper、UISwitch、UITextView、UIAlertController
- tmux的使用方法和个性化配置
- activiti实战系列 并行网关(parallelGateWay)
- activiti实战系列 并行网关(parallelGateWay)
- 再学学flash吧 小学生都教不会了
- 年月日计算