数据结构之图

/*

 *@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 ,否则返回 false

		if(v1<0||v1>=vertices.size()||v2<0||v2>=vertices.size())

		{

			return true;

		}else

		{

			return false;

		}

	}

	public boolean checkOut(int v)

	{

		// 如果越界则返回 true ,否则返回 false

		if(v<0||v>=vertices.size())

		{

			return true;

		}else

		{

			return false;

		}

	}

	

	public void deleteEdge(Edge edge)throws Exception

	{

		deleteEdge(edge.start,edge.end);

	}

	//取给定节点的第一个邻接节点,诺存在,则返回该节点的下标序号,否则返回-1

	public 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后的邻接节点,诺存在,则返回该节点的下标序号,否则返回-1

	public 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 ();

			

		}

		

		

	}

	//每对顶点之间的最短路径-floyd

	public 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];

		 			}

		 		}

		 	}

		 }

	}

	//最小代价生成树-prim

	public 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()+" ");

	}

}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值