您的位置:首页 > 理论基础 > 数据结构算法

图的邻接表表示、广度优先、深度优先搜索

2015-05-18 21:58 666 查看
图,就是我们在数据结构中学到的图,它是一种存储信息的结构。图是一类在实际应用中非常常见的数据结构,当数据规模大到一定程度时,如何对其进行高效计算即成为迫切需要解决的问题。最常见的大规模图数据的例子就是互联网网页数据,网页之间通过链接指向形成规模超过500 亿节点的巨型网页图。再如,Facebook 社交网络也是规模巨大的图,仅好友关系已经形成超过10 亿节点、千亿边的巨型图,考虑到Facebook 正在将所有的实体数据节点都构建成网状结构,其最终形成的巨型网络数据规模可以想见其规模。要处理如此规模的图数据,传统的单机处理方式显然已经无能为力,必须采用由大规模机器集群构成的并行图数据库。在处理图数据时,其内部存储结构往往采用邻接矩阵或邻接表的方式,在大规模并行图数据库场景下,邻接表的方式更加常用,大部分图数据库和处理框架都采用了这一存储结构。

本程序是基于图的邻接表存储方式实现的。遗憾的是没有实现带权图,有实现带权图的朋友欢迎留言指教!或加Q:374741295



package linkListGraph;

import java.util.ArrayList;
import java.util.Iterator;

/**
* @ClassName: Graph
* @Description: 图结构实现,封装了图的dfs、bfs遍历算法
* @author zhoupengcheng
* @version 2015年5月17日下午5:07:34
*/
public class Graph {
private ArrayList<Vertex> vertexList;// 用一个ArrayList保存图中的所有结点
private boolean isDirected = false;// 标记是否为有向图
private int nVerts = 0;// 保存总的顶点数

private StackX theStack;// 深度优先搜寻时使用
private Queue theQueue; // 广度优先搜索时使用
private ArrayList<Vertex> bfs;// 在bfs函数中使用,保存bfs得到的结果序列
private ArrayList<Vertex> dfs;// 在dfs函数中使用,保存dfs得到的结果序列

public Graph() {
vertexList = new ArrayList<Vertex>();
dfs = new ArrayList<Vertex>();
bfs = new ArrayList<Vertex>();
}

public Graph(boolean is) {
this();
this.isDirected = is;
}

public boolean isDirected() {
return this.isDirected;
}

public ArrayList<Vertex> getVertexList() {
return vertexList;
}

public ArrayList<Vertex> getDFS() {
return dfs;
}

public ArrayList<Vertex> getBFS() {
return bfs;
}

public void addVertex(Vertex vertex) {
vertex.setIndex(nVerts);
vertexList.add(vertex);
nVerts++;
}

public void addEdge(int start, int end) {
vertexList.get(start).addAdj(vertexList.get(end));
if (!isDirected) {
vertexList.get(end).addAdj(vertexList.get(start));
}
}

public int getVertsCount() {
return nVerts;
}

//深度优先迭代器
public Iterator dfsIterator(){
dfs();
return new DfsIterator();
}

//广度优先迭代器
public Iterator bfsIterator(){
bfs();
return new BfsIterator();
}

// 打印邻接表
public void displayGraph() {
for (int i = 0; i < vertexList.size(); i++) {
printVertx(vertexList.get(i));
}
}

public void printVertx(Vertex vertex) {
ArrayList<Vertex> next = vertex.getAdj();
if (next == null) {
System.out.println(vertex.toString() + " 无邻接点!");
} else {
System.out.print(vertex.toString() + "邻接表:");
for (int i = 0; i < next.size(); i++) {
System.out.print(next.get(i).label + " ");
}
System.out.println();
}
}

// 深度优先遍历
public void dfs() {
theStack = new StackX(nVerts);
vertexList.get(0).wasVisted = true;
dfs.add(vertexList.get(0));
theStack.push(vertexList.get(0));
Vertex vertex;
while (!theStack.isEmpty()) {
vertex = getAdjVertex((Vertex) theStack.peek());
if (vertex == null) {
theStack.pop();
} else {
vertex.wasVisted = true;
dfs.add(vertex);
theStack.push(vertex);
}
}
// ------遍历完成,清除所有访问标志位--------
for (int i = 0; i < getVertsCount(); i++) {
vertexList.get(i).wasVisted = false;
}

}

// 广度优先遍历
public void bfs() {
theQueue = new Queue(nVerts);
vertexList.get(0).wasVisted = true;
bfs.add(vertexList.get(0));
theQueue.insert(vertexList.get(0));
Vertex vertex1;
while (!theQueue.isEmpty()) {
Vertex vertex2 = (Vertex) theQueue.remove();
while ((vertex1 = getAdjVertex(vertex2)) != null) {
vertex1.wasVisted = true;
bfs.add(vertex1);
theQueue.insert(vertex1);
}
}
// ------遍历完成,清除所有访问标志位--------
for (int i = 0; i < getVertsCount(); i++) {
vertexList.get(i).wasVisted = false;
}
}

// 返回vertex顶点的一个未曾访问过的邻接点
public Vertex getAdjVertex(Vertex vertex) {
ArrayList<Vertex> adjVertexs = vertex.getAdj();
for (int i = 0; i < adjVertexs.size(); i++) {
if (!adjVertexs.get(i).wasVisted) {
return adjVertexs.get(i);
}
}
return null;
}

//专门写个迭代器来遍历结果
private abstract class GraphIterator implements Iterator {
int count = 0;
public GraphIterator() {
}

public boolean hasNext() {
return count != getVertsCount() ;
}

public Object next() {
// TODO Auto-generated method stub
return null;
}

public void remove() {
// TODO Auto-generated method stub
}
}

// 深度优先迭代
private class DfsIterator extends GraphIterator {
public DfsIterator() {
super();
}

public Vertex next() {
return dfs.get(count++);
}
}

// 广度优先迭代
private class BfsIterator extends GraphIterator {
public BfsIterator() {
super();
}

public Object next() {
return bfs.get(count++);
}
}
}
package linkListGraph;

import java.util.Iterator;

public class GraphApp {

public static void main(String[] args) {
Graph myGraph = new Graph();
Vertex vertex;
myGraph.addVertex(new Vertex('A'));//位置为0
myGraph.addVertex(new Vertex('B'));//位置为1
myGraph.addVertex(new Vertex('C'));//位置为2
myGraph.addVertex(new Vertex('D'));//位置为3
myGraph.addVertex(new Vertex('E'));//位置为4
myGraph.addVertex(new Vertex('F'));//位置为5
myGraph.addVertex(new Vertex('G'));//位置为6
myGraph.addVertex(new Vertex('H'));//位置为7
myGraph.addVertex(new Vertex('I'));//位置为8
myGraph.addVertex(new Vertex('J'));//位置为9
myGraph.addVertex(new Vertex('K'));//位置为10
myGraph.addEdge(0, 1);
myGraph.addEdge(0, 2);
myGraph.addEdge(0, 3);
myGraph.addEdge(1, 4);
myGraph.addEdge(1, 5);
myGraph.addEdge(3, 7);
myGraph.addEdge(3, 10);
myGraph.addEdge(4, 6);
myGraph.addEdge(5, 6);
myGraph.addEdge(5, 9);
myGraph.addEdge(7, 8);
myGraph.addEdge(8, 10);
myGraph.displayGraph();

System.out.println("深度优先迭代遍历:");
for (Iterator iterator = myGraph.dfsIterator(); iterator.hasNext();) {
vertex = (Vertex) iterator.next();
System.out.println(vertex.toString());
}

System.out.println("广度优先迭代遍历:");
for (Iterator iterator = myGraph.bfsIterator(); iterator.hasNext();) {
vertex = (Vertex) iterator.next();
System.out.println(vertex.toString());
}
}
}


package linkListGraph;
import java.util.ArrayList;
/**
* @ClassName:   Vertex
* @Description: 顶点类,表示图中存储的顶点
* @author       zhoupengcheng
* @version      2015年5月17日下午4:31:54
*/
public class Vertex {
public char label;
public boolean wasVisted;
public int indexId;//顶点的标号
//由于采用"邻接表"方式表示图,所以每个顶点对象持有一个邻接表adjList
private ArrayList<Vertex> adjacentList = null;

public Vertex(char lab) // constructor
{
this.label = lab;
this.wasVisted = false;
}

// 为节点添加邻接点
public void addAdj(Vertex ver) {
if (adjacentList == null)
adjacentList = new ArrayList<Vertex>();
adjacentList.add(ver);
}

//返回一个顶点的邻接表,在遍历图时需根据邻接表找下一个节点
public ArrayList<Vertex> getAdj() {
return this.adjacentList;
}

public void setIndex(int index) {
this.indexId = index;
}

public String toString() {
return "顶点 :" + label+" ";
}
}


package linkListGraph;
/*
* 深度优先遍历需要借助栈保存当前访问过的顶点
*/
public class StackX {
//private int size=20;
private Vertex[] stackArray;//用数组实现栈的存储(理论上链栈效率更高)
private int top;
public StackX(int size){
stackArray=new Vertex[size];
top=-1;
}

public Vertex pop(){
return stackArray[top--];
}

public Vertex peek(){
return stackArray[top];
}

public boolean isEmpty(){
return top==-1;
}

public void push(Vertex vertex) {
// TODO Auto-generated method stub
stackArray[++top]=vertex;
}
}


package linkListGraph;
/*
* 广度优先需要借助队列保存当前已经访问过的顶点
*/
public class Queue {
private int maxSize=20;
private int front;//队头指针
private int rear;//队尾指针
private Vertex[] queArray;//用数组实现队列的存储(理论上链队列效率更高)

public Queue(int size) {
this.maxSize=size;
queArray = new Vertex[maxSize];
front = 0;
rear = -1;
}

public void insert(Vertex value) {
if (rear == maxSize - 1)
rear = -1;
queArray[++rear] = value;
}

// 返回被删除的元素
public Vertex remove() {
if (front == maxSize)
front = 0;
Vertex temp = queArray[front++];
return temp;
}

public boolean isEmpty() {
return (rear+1==front||(front+maxSize-1==rear));
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java 数据结构 算法