数据结构之图

来源:互联网 发布:白色西服知乎 编辑:程序博客网 时间:2024/05/03 23:39
/* *@date:08-07-10 *@descript:图的实现与应用 **/public class AdjMatGraph{public final int maxWeight=10000;//无穷大常量public final int[] [] D1=new int[100][100];//最大顶点数public final int[] [] P1=new int[100][100];private SeqList vertices;//存储节点的顺序表private int [][] edges;//存储边的二维数组private int numOfEdges;//边的条数public AdjMatGraph(){}public AdjMatGraph(int maxV){vertices=new SeqList(maxV);//创建顶点数组edges=new int[maxV][maxV];for (int i = 0; i<maxV; i++)//初始化各边的权值为无穷大    {    for (int j = 0; j<maxV; j++)    {    if(i==j)    {    edges[i][j]=0;    }else    {    edges[i][j]=maxWeight;    }    }    }}public AdjMatGraph createGraph(Object[] vertices,Edge[] edges){try{// 插入顶点for(int i=0;i<vertices.length;i++){insertVertex(vertices[i]);}//插入边for (int i = 0; i<edges.length; i++)    {    insertEdge(edges[i].start,edges[i].end,edges[i].weight);    }    }    catch (Exception ex){    ex.printStackTrace();    return null;    }    return this;}//使用给定的顶点数组和边的数组创建一个基于邻接矩阵存储的图public static AdjMatGraph createAdjMatGraph(Object[] vertices,Edge[] edges){AdjMatGraph g=new AdjMatGraph(vertices.length);g=g.createGraph(vertices,edges);if(g!=null){return g;}else{return null;}}//返回指定数据元素的下标public int locateVertex(Object vertex)throws Exception{return vertices.locate(vertex);}//插入顶点public void insertVertex(Object vertex)throws Exception{vertices.insert(vertices.size(),vertex);}// 插入边public void insertEdge(int v1,int v2,int weight)throws Exception{if(checkOut(v1,v2)){throw new Exception("参数越界错误");}else{edges[v1][v2]=weight;this.numOfEdges++;//边的数目加 1}}public void insertEdge(Edge edge)throws Exception{insertEdge(edge.start,edge.end,edge.weight);}// 删除边public void deleteEdge(int v1,int v2)throws Exception{//调用判断函数,检查是否越界if(checkOut(v1,v2)){//参数越界throw new Exception("参数越界错误");}else if(edges[v1][v2]==maxWeight||v1==v2){throw new Exception("该边不存在!");}else{edges[v1][v2]=maxWeight;//将该边的权值设为无穷大,即为删除该边this.numOfEdges--;}}//检查是否越界public boolean checkOut(int v1,int v2){// 如果越界则返回 true ,否则返回 falseif(v1<0||v1>=vertices.size()||v2<0||v2>=vertices.size()){return true;}else{return false;}}public boolean checkOut(int v){// 如果越界则返回 true ,否则返回 falseif(v<0||v>=vertices.size()){return true;}else{return false;}}public void deleteEdge(Edge edge)throws Exception{deleteEdge(edge.start,edge.end);}//取给定节点的第一个邻接节点,诺存在,则返回该节点的下标序号,否则返回-1public int getFirstAdjVex(int v)throws Exception{if(checkOut(v)){//参数越界throw new Exception("参数越界错误");}for (int col = 0; col<vertices.size(); col++)    {    if(edges[v][col]>0 && edges[v][col]<maxWeight)    {    return col;    }    }return -1;}//取给定节点V1的邻接点V2后的邻接节点,诺存在,则返回该节点的下标序号,否则返回-1public int getNextAdjVex(int v1,int v2)throws Exception{//判断参数是否越界if(checkOut(v1,v2)){//参数越界throw new Exception("参数越界错误");}for(int col=v2+1;col<vertices.size();col++){if(edges[v1][col]>0 && edges[v1][col]<maxWeight){return col;}}return -1;}//返回图中的顶点数public int getNumOfVertices(){return vertices.size();}//返回图中边的数目public int getNumOfEdges(){return numOfEdges;}//返回节点V中的数据元素public Object getValue(int v)throws Exception{return this.vertices.getData(v);}//返回边的值public int getWeight(int v1,int v2)throws Exception{if(checkOut(v1,v2)){throw new Exception("参数越界错误");}return edges[v1][v2];}//深度优先遍历指定的顶点. v为初始顶点,visited访问标记数组,vs为如何处理已访问的元素public void DFSearch(int v,boolean[] visited,Visited vs)throws Exception{vs.visit(getValue(v));//访问当前节点visited[v]=true;//标记为已访问int w=getFirstAdjVex(v);//获得当前节点的第一个邻接点while(w!=-1){if(!visited[w])//如果还有未访问的节点{DFSearch(w,visited,vs);}w=getNextAdjVex(v,w);}}//深度优先遍历public void DFSTravers(Visited vs)throws Exception{//创建访问标记数组,初始值为味访问boolean[] visited=new boolean[getNumOfVertices()];for(int i=0;i<visited.length;i++){visited[i]=false;}//对图中节点进行遍历for(int i=0;i<visited.length;i++){//如果该节点未被访问过,则以深度优先算法进行遍历if(!visited[i]){this.DFSearch(i,visited,vs);}}}//深度优先算法遍历指定节点public void BFSearch(int v,boolean[] visited,Visited vs)throws Exception{int u,w;SeqQueue queue=new SeqQueue(getNumOfVertices());//创建顺序队列vs.visit(getValue(v));//访问当前节点visited[v]=true;//设置访问标记queue.EnQueue(new Integer(v));//当前节点入队列while(!queue.isEmpty()){u=((Integer)queue.DeQueue()).intValue();w=getFirstAdjVex(u);//取节点u的第一个邻接节点while(w!=-1)//当邻接节点存在循环时{if(!visited[w]){vs.visit(getValue(w));visited[w]=true;queue.EnQueue(new Integer(w));}w=this.getNextAdjVex(u,w);}}}public void BFSTravers(Visited vs)throws Exception{//创建访问标记数组,初始值为味访问boolean[] visited=new boolean[getNumOfVertices()];for(int i=0;i<visited.length;i++){visited[i]=false;}//对图中节点进行遍历for(int i=0;i<visited.length;i++){//如果该节点未被访问过,则以广度优先算法进行遍历if(!visited[i]){this.BFSearch(i,visited,vs);}}}//单源点最短路径-DijKstra, v1为源点,n为图中顶点个数public void DijKstra(AdjMatGraph G,int v1,int n){int [] D=new int[getNumOfVertices()];int [] P=new int[getNumOfVertices()];boolean[] S=new boolean[getNumOfVertices()];int v,i,w,min;for(v=1;v<=n;v++){S[v]=false;//初始化最短路径终点D[v]=G.edges[v1][v];//初始化最短路径if(D[v]<maxWeight){P[v]=v1;}else{P[v]=0;}}D[v1]=0;S[v1]=true;//初始化,将V1加入S集//开始主循环,每次求得V1到其余V顶点的最短路径for(i=2;i<n;i++){min=maxWeight;for(w=1;w<=n;w++){if(!S[w] && D[w]<min){v=w;//w顶点离v1最近min=D[w];}}S[v]=true;for(w=1;w<=n;w++){if(!S[w] && (D[v]+G.edges[v][w]<D[w])){D[w]=D[v]+G.edges[v][w];P[w]=v;}}}System.out.println ("路径长度: "+"/t"+"路径: ");for(i=1;i<=n;i++){System.out.print(D[i]-1+"/t"+"/t");System.out.print(i);v=P[i];while(v!=0){System.out.print("<-"+v);v=P[v];}System.out.println ();}}//每对顶点之间的最短路径-floydpublic void Floyd(AdjMatGraph G,int n){ int i,j,k,v,w; for(i=1;i<=n;i++) { for(j=1;j<=n;j++) { if(G.edges[i][j]!=maxWeight)// !=maxWeight即从i到j有直接路径 { P1[i][j]=j; }else { P1[i][j]=0; } D1[i][j]=G.edges[i][j]; } } for(k=1;k<=n;k++) { for(i=1;i<=n;i++) { for(j=1;j<=n;j++) { //从i经过k到j的一条路径更短 if(D1[i][k]+D1[k][j]<D1[i][j]) { D1[i][j]=D1[i][k]+D1[k][j]; P1[i][j]=P1[i][k]; } } } }}//最小代价生成树-primpublic void Prim(){}public static void main(String[] args)    {    String[] vertex={"v1","v2","v3","v4","v5","v6","v7","v8"};    Edge[] edges={    new Edge(0,1,1),    new Edge(0,2,1),    new Edge(1,3,1),    new Edge(1,4,1),    new Edge(3,7,1),    new Edge(4,7,1),    new Edge(2,5,1),    new Edge(5,6,1),    new Edge(2,6,1),    new Edge(1,0,1),    new Edge(2,0,1),    new Edge(3,1,1),    new Edge(4,1,1),    new Edge(7,3,1),    new Edge(7,4,1),    new Edge(5,2,1),    new Edge(6,5,1),    new Edge(6,2,1)         };        try{    //创建图    AdjMatGraph amg=AdjMatGraph.createAdjMatGraph(vertex,edges);        //求图中顶点的数目    System.out.println ("图中的顶点数为:"+amg.getNumOfVertices());        //求图中边的数目    System.out.println ("图中的边数为:"+amg.getNumOfEdges());        //深度优先遍历    System.out.println ("图的深度优先遍历顺序:");    amg.DFSTravers(new Visited());    System.out.println ();        //广度优先遍历    System.out.println ("图的广度优先遍历顺序:");    amg.BFSTravers(new Visited());    System.out.println ();        //单源点最短路径-DijKstra    amg.DijKstra(amg,0,amg.getNumOfVertices()-1);        //每对顶点之间的最短路径-floyd    amg.Floyd(amg,amg.getNumOfVertices()-1);    int start,end,k;    start=1;    end=7;    k=amg.P1[start][end];    if(k==0)    {    System.out.println ("从顶点"+start+"到顶点"+end+"无路径!");    }else    {    System.out.print("从顶点"+start+"到顶点"+end+"的最短路径是:"+start);    while(k!=end)    {    System.out.print("->"+k);    k=amg.P1[k][end];    }    System.out.print("->"+end);    System.out.println("路径长度:"+amg.D1[start][end]);    }    }    catch (Exception ex){    ex.printStackTrace();    }    }}class Edge //边类{public int start;//起点public int end;//终点public int weight;//权值public Edge(){}public Edge(int start,int end,int weight){this.start=start;this.end=end;this.weight=weight;}}class Visited{public void visit(Object item)throws Exception{System.out.print (item.toString()+" ");}}
原创粉丝点击