图,就是我们在数据结构中学到的图,它是一种存储信息的结构。图是一类在实际应用中非常常见的数据结构,当数据规模大到一定程度时,如何对其进行高效计算即成为迫切需要解决的问题。最常见的大规模图数据的例子就是互联网网页数据,网页之间通过链接指向形成规模超过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)); } }
时间: 2024-10-25 22:50:59