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

来源:互联网 发布:网络教育的利弊辩论赛 编辑:程序博客网 时间:2024/05/27 06:13

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

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);}@Overridepublic String toString(){// TODO Auto-generated method stubreturn "[" + pointIndex + "]" + data + "  ";}}
1.3、邻接边

/* * 此类代表邻接边的信息 */public class AdjacentEdge{int adjacentPointIndex; //邻接边顶点的编号,此处的编号是顶点数组中对应的下标int edgeInfo;//邻接边的信息,即权值,若无则为0public 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