图1---------------图的表示和遍历算法

来源:互联网 发布:uv在淘宝什么意思 编辑:程序博客网 时间:2024/06/08 17:23

图的表示方法:

邻接矩阵法(太浪费空间,但确实把所有信息都表示了出来,计算度或者各种操作的话很方便,当然用无向图的对称性、只存放非0结点可以优化)

邻接表(算比较好的一种方法,但是对于有向图计算入度必须遍历,用逆邻接表、十字链表优化)

十字链表(和邻接表太类似)


遍历算法:

图是标准的多对多结构,因此不构成环并且不重复访问vertex需要一个标志数组visited,循环这个保证全部都访问,遍历过程中可以有DFS和BFS

DFS:递归方式,首先访问vertex,循环找邻接节点,找到并且该vertex没有被访问过,将顶点当成参数进入下一层。

BFS:需要堆栈配合,找到自己邻接的顶点如果没有被访问过则访问并将其入栈,然后用stack非空控制循环直到全部访问过。


还有一些计算连通分量个数、度的问题,就是遍历算法的应用。


代码(结构写的有点乱,回头看的时候可以优化下):

package nuaa.ds;public class Graph {private String[] vertexes;//邻接矩阵法所private int[][] vr;       //使用的成员变量private CreateGraph g;private VertexNode[] vertexNodes;//邻接表所使用的成员变量/** * 图的构成实在太多,写个标准无向图熟悉算法 * 顶点ABCD(其中BC不连)彼此互连,EF彼此互连 */public Graph(CreateGraph c){this.g = c;switch(c){case AdjacencyMatrix://邻接矩阵vertexes = new String[]{"A","B","C","D","E","F"};//ABCDEF6个顶点vr = new int[6][6];vr[0] = new int[]{0,1,1,1,0,0};//邻接矩阵法表示边,相连值为1,不连值为0vr[1] = new int[]{1,0,0,1,0,0};//优点是所有信息全部显示出来vr[2] = new int[]{1,0,0,1,0,0};//这样顶点的度等计算或者对图的所有操作都比较容易vr[3] = new int[]{1,1,1,0,0,0};//缺点也很明显vr[4] = new int[]{0,0,0,0,0,1};//存储空间极大的浪费vr[5] = new int[]{0,0,0,0,1,0};//当然通过使用对称或者只存储非0元素可以优化break;case AdjacencyTable://邻接表表示,省了很多存储空间,//但有时会带来不便,比如求有向图的某个节点的入度//结点数组的初始化vertexNodes = new VertexNode[6];String[] temp = new String[]{"A","B","C","D","E","F"};for(int i=0;i<vertexNodes.length;i++){vertexNodes[i] = new VertexNode(temp[i]);}//结点数组连接的边结点的初始化//写de好麻烦,还不如由输入流输进来循环构造。但每次测试重新输入图结构也很烦。//顶点A的初始化vertexNodes[0].arcNode = new ArcNode(1);vertexNodes[0].arcNode.arcNode = new ArcNode(2);vertexNodes[0].arcNode.arcNode.arcNode = new ArcNode(3);//顶点B的初始化vertexNodes[1].arcNode = new ArcNode(0);vertexNodes[1].arcNode.arcNode = new ArcNode(3);//顶点C的初始化vertexNodes[2].arcNode = new ArcNode(0);vertexNodes[2].arcNode.arcNode = new ArcNode(3);//顶点D的初始化vertexNodes[3].arcNode = new ArcNode(0);vertexNodes[3].arcNode.arcNode = new ArcNode(1);vertexNodes[3].arcNode.arcNode.arcNode = new ArcNode(2);//顶点E的初始化vertexNodes[4].arcNode = new ArcNode(5);//顶点F的初始化vertexNodes[5].arcNode = new ArcNode(4);}}//求连通分量个数或者连通生成树也是遍历算法public void traversalByDFS(){this.traversalByDFS(this.g);}private void traversalByDFS(CreateGraph c){//深度优先算法访问图boolean[] visited;if(c==CreateGraph.AdjacencyTable){visited = new boolean[vertexNodes.length];//java默认都为false}else{visited = new boolean[vertexes.length];//java默认都为false}switch(c){case AdjacencyMatrix://图是用邻接表表示的深度优先遍历算法for(int i=0;i<vertexes.length;i++){if(!visited[i]){mTraversalByDFS(visited,i);}}break;case AdjacencyTable:for(int i=0;i<vertexNodes.length;i++){if(!visited[i]){tTraversalByDFS(visited,i);}}}}private void mTraversalByDFS(boolean[] visited,int index){visit(vertexes[index]);//和二叉树一样的问题,访问图结点可能会做些其他操作//还是从外部当成函子传入进来比较合适//对应的vertexes数组也要改成Object[],这样的封装更好visited[index] = true;for(int i=0;i<vr[index].length;i++){//循环找到下一个结点if(vr[index][i]==1&&!visited[i]){//有连接的未访问的结点mTraversalByDFS(visited,i);//访问该结点}}}private void tTraversalByDFS(boolean[] visited,int index){visit(vertexNodes[index]);visited[index] = true;ArcNode p = vertexNodes[index].arcNode;while(null!=p){if(!visited[p.serialNumber]){tTraversalByDFS(visited,p.serialNumber);}p = p.arcNode;}}public void traversalByBFS(){this.traversalByBFS(g);}private void traversalByBFS(CreateGraph c){boolean[] visited;if(c==CreateGraph.AdjacencyTable){visited = new boolean[vertexNodes.length];//java默认都为false}else{visited = new boolean[vertexes.length];//java默认都为false}Stack<VertexNode> stack = new Stack<VertexNode>();switch(c){case AdjacencyMatrix://图是用邻接表表示的深度优先遍历算法for(int i=0;i<vertexes.length;i++){if(!visited[i]){mTraversalByBFS(visited,i);}}break;case AdjacencyTable:for(int i=0;i<vertexNodes.length;i++){if(!visited[i]){tTraversalByBFS(stack,visited,i);}}}}private void tTraversalByBFS(Stack<VertexNode> stack,boolean[] visited,int index){stack.push(vertexNodes[index]);visit(vertexNodes[index]);visited[index] = true;ArcNode p ;while(!stack.isEmpty()){p = stack.pop().arcNode;while(p!=null){if(!visited[p.serialNumber]){stack.push(vertexNodes[p.serialNumber]);visit(vertexNodes[p.serialNumber]);visited[p.serialNumber] = true;}p = p.arcNode;}} }private void mTraversalByBFS(boolean[] visited,int index){Stack<Integer> stack = new Stack<Integer>();stack.push(index);visit(vertexes[index]);visited[index] = true;while(!stack.isEmpty()){for(int i=0;i<vr[index].length;i++){if(vr[index][i]==1&&!visited[i]){stack.push(i);visit(vertexes[i]);visited[i] = true;}}index = stack.pop();}}private void visit(String vertex){System.out.print(vertex+" ");}private void visit(VertexNode node){System.out.println(node.vertex);} class VertexNode{String vertex;ArcNode arcNode;public VertexNode(String vertex){this.vertex = vertex;}}class ArcNode{int serialNumber;//存放边连着的节点在vertexNode数组里面的位置ArcNode arcNode;public ArcNode(int serialNumber){this.serialNumber = serialNumber;}}}

一些盲点: 十字链表表示法太相似没有写,邻接矩阵法用广义表的方式对空间进行优化,然后计算连通分量、度可以用来复习下遍历算法。

原创粉丝点击