您的位置:首页 > 其它

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

2016-04-16 08:49 281 查看
今天介绍图(森林)的深度优先历遍和广度优先历遍

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);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: