1. 程式人生 > >求解羅馬尼亞度假問題,找到從Arad到Bucharest的一條路徑,java實現。

求解羅馬尼亞度假問題,找到從Arad到Bucharest的一條路徑,java實現。

運用迪傑斯特拉演算法(Dijkstra演算法),找到Arad到Bucharest的最短路徑。註釋掉的內容不用管。 圖通過鄰接表實現,為無向圖

import java.util.Scanner;

public class path {
static Scanner s=new Scanner(System.in);
	
	
	public static void main(String[] args) {
		String[] names={"Drobeta","Mehadia","Lugoj","Timisoara","Arad","Zerind","Oradea","Craiova","Rimnicu Vilcea","Sibiu","Pitesti",
				"Bucharest","Fagaras"};
		arc[] arc={new arc("Arad","Zerind",75),new arc("Arad","Sibiu",140),new arc("Arad","Timisoara",118),new arc("Timisoara","Lugoj",111),
				new arc("Lugoj","Mehadia",70),new arc("Mehadia","Drobeta",75),new arc("Drobeta","Craiova",120),new arc("Craiova","Pitesti",138),new arc("Craiova","Rimnicu Vilcea",146),
				new arc("Pitesti","Bucharest",101),new arc("Bucharest","Fagaras",211),
				new arc("Rimnicu Vilcea","Pitesti",97),new arc("Rimnicu Vilcea","Sibiu",80),new arc("Sibiu","Fagaras",99),new arc("Sibiu","Oradea",151),new arc("Oradea","Zerind",71)};
		Graph gra = createGraph(names,arc);
		System.out.println(gra);
		int path[]=Dijkstra(gra,"Arad");
		Dispath(gra,path,"Arad","Bucharest");
	}
	
	static Graph createGraph(String[] names,arc[] arc){//String儲存節點名稱,arc儲存每一個節點的邊所到到的邊和權值
		
			int n=names.length;
			Graph graph =new Graph(n);
			for(int i=0;i<n;i++  ){
				graph.graph[i]=new vexnode();
				graph.graph[i].name=names[i];
									}
			for(int i=0;i<arc.length;i++){
				add(arc[i].name1,arc[i].name2,arc[i].weight,graph);
				add(arc[i].name2,arc[i].name1,arc[i].weight,graph);
								}	
			
			return graph;
								
	
	}
	
	static void add(String name1,String name2,int weight,Graph graph){
		int i=find(name1,graph);
		int j=find(name2,graph);
	if(i==-1||j==-1)
	{
		System.out.println(name1+"->"+name2+"失敗");
		return;
		
	}
			
		
				
					arcnode ar=new arcnode();
					ar.ver=j;
					ar.weight=weight;
					ar.nextarc=null;
					arcnode pre = null;
					arcnode temp=graph.graph[i].firstarc;
					if(temp==null){//頂點之前無邊
						graph.graph[i].firstarc=ar;
					}
					else
					    {while(temp!=null)//頂點之前無邊
					 {
						pre=temp;
						temp=temp.nextarc;
						
					 }
					pre.nextarc=ar;
					       }
	}
	
	static int find(String name,Graph graph){
		int n=graph.graph.length;
		for(int i=0;i<n;i++  )
			if(graph.graph[i].name.equals(name))
				return i;
		return -1;
		
	}
	static int[] Dijkstra(Graph graph,String start){
	int v=find(start,graph);
	int[] path=new int[graph.graph.length];
	for(int i=0;i<graph.graph.length;i++)
		path[i]=-1;
	int[] dist=new int[graph.graph.length];
	for(int i=0;i<graph.graph.length;i++)
		dist[i]=1000000;
	int[] s=new int[graph.graph.length];//s儲存那哪些結點已經被訪問過
	if(v==-1){
		System.out.println("無"+start+"這個節點");
		return null;
	}
		
	arcnode p =graph.graph[v].firstarc;
	while(p!=null)
	{
		path[p.ver]=v;
		dist[p.ver]=p.weight;
		p=p.nextarc;
	}
	s[v]=1;//頂點V加入s中
	int u=0,mindis=1000000;
	for(int i=0;i<graph.graph.length;i++){
		mindis=1000000;
		for(int j=0;j<graph.graph.length;j++)
		if((s[j]==0)&&dist[j]<mindis){
			u=j;
			mindis=dist[j];	
		}
		s[u]=1;//頂點u加入s中
		p =graph.graph[u].firstarc;
		while(p!=null)
		    {
			if(s[p.ver]==0)
			if(dist[p.ver]>dist[u]+p.weight){
				dist[p.ver]=dist[u]+p.weight;
				path[p.ver]=u;
			    }
			    p=p.nextarc;
		     }
	}
	return path;
	}
	static void Dispath(Graph graph,int[] path,String start,String end){
		int sta=find(start,graph);
		int en=find(end,graph);
		if(sta==-1||en==-1){
			System.out.println("沒有找到相關結點");
			return;
		}
		if(path[en]==-1){
			System.out.println("路徑有誤");
			return;
		}
		else{
			int temp=0,i=1;
			int[] path1=new int[path.length];
			path1[0]=en;
			temp=path1[0];
			while(path[temp]!=sta){
				path1[i]=path[temp];
				temp=path1[i];
				i++;
			}
			path1[i]=sta;
			System.out.println(start+"到"+end+"最短路徑為:");
			for(int j=i;j>0;j--){
				System.out.print(graph.graph[path1[j]].name+"-->");
			}
			System.out.println(graph.graph[path1[0]].name);
			}
		
	}
	
/*static Graph createGraph(){//互動介面
	
	
	//互動介面
	
		int n;
		System.out.println("請輸入總節點數:");
		n=s.nextInt();
		Graph graph =new Graph(n);
		System.out.println("請輸入所有的節點名稱,中間用空格隔開");
		for(int i=0;i<n;i++  ){
			String name=s.next();
			graph.graph[i]=new vexnode();
			graph.graph[i].name=name;
								}
		for(int i=0;i<n;i++  ){
			while (true){
			System.out.println("請輸入節點"+graph.graph[i].name+"的邊,先輸入這條邊所到的節點名稱,空格,輸入權值,輸入0結束當前節點邊的建立");
			String name=s.next();
			if(name.equals("0"))
			  break;
			int weight=s.nextInt();
			for(int j=0;j<n;j++){
				if(graph.graph[j].name.equals(name))
				{
					arcnode arc=new arcnode();
					arc.ver=j;
					arc.weight=weight;
					arc.nextarc=null;
					arcnode pre = null;
					arcnode temp=graph.graph[i].firstarc;
					if(temp==null){//頂點之前無邊
						graph.graph[i].firstarc=arc;
						System.out.println(graph.graph[i].name+"到"+name+"新增成功");
						break;
					}
					while(temp!=null)//頂點之前無邊
					{
						pre=temp;
						temp=temp.nextarc;
						
					}
					System.out.println(graph.graph[i].name+"到"+name+"新增成功");
					pre.nextarc=arc;
					      }
								}
							}	
			                         }
							return graph;}	*/															
}


class arcnode{//arc,網弧節點
	int ver=-1;//指向邊結點
    int weight=0;//權值
    arcnode nextarc=null;
}

class vexnode//vertex頂點節點
{
    String name;
    arcnode firstarc=null;//指向第一條弧節點
}  //頂點結點

class Graph{//儲存圖
	vexnode[]  graph;//一個叫graph的vexnode
	Graph(int num){
		graph=new vexnode[num];
	}
	
	public String toString(){
		String[] names=new String[graph.length];
		for(int i=0;i<graph.length;i++)
		{
			names[i]=graph[i].name;
			
		}
		
		for(int i=0;i<graph.length;i++)
		{
			arcnode pre = null;
			arcnode p =graph[i].firstarc;
			while(p!=null)
			{
				names[i]=names[i]+" "+graph[p.ver].name+" "+p.weight;
				p=p.nextarc;
				
			}
			
		}
		String s="";
		for(int i=0;i<graph.length;i++)
			s+=names[i]+"\n";
		return s;
		
	}
}
class arc{
	String name1=null;
	String name2=null;
	int weight;
	arc(String name1,String name2,int weight){
		this.name1=name1;
		this.name2=name2;
		this.weight=weight;
		
	}
}

結果: 在這裡插入圖片描述