1. 程式人生 > >[Java]一個簡單的計算有向賦權圖最短距離的程式碼

[Java]一個簡單的計算有向賦權圖最短距離的程式碼

在一個有向賦權圖中尋找點a到點b的最短距離,是個簡單問題。

寫了段程式碼,記錄在這裡吧。

以下面的這個圖為例:


計算從點0到點5的最短距離

解決方法:

(1)讀取路線資料,用二維陣列b[i][j],表示點i到點j可以走,距離為其數值。

(2)建立一個堆疊H,壓入起點,堆疊的節點為這個點的編號和它可以到達的點的連結串列。

(3)彈出H最上面的點Last的可到達連結串列T的最後一個可以到達的點M,將這個點號壓入H中。【1】如果H空了,則所有可能找完了。【2】如果T為空,則這個Last點找完了,可以彈出,繼續尋找了。

(4)判斷當前形成的H是不是表示找到了一個新的最短路徑。【1】如果找到了,儲存這個路徑到rList[i],儲存路徑長度到rLen[i],表示起點到點i的最短路徑和最短路徑長度。【2】如果找到的路徑長度大於之前找到的,則這個結果不必要保留,彈出這個點。

(5)重複(3)

執行結果為:

This is a program to calculate the shortest path of a map.
len=6
Path=0 3 6 5 


程式碼如下:

【1】Mainclass.java

/**
 * Created by Firwood on 14-9-23.
 */
public class Mainclass {
	public static final int PointNum = 7;
	public static void main(String[] args){
		System.out.println("This is a program to calculate the shortest path of a map.");
		/*
		int [][] b = new int[PointNum][PointNum];
		for(int i=0;i<PointNum;i++){
			for(int j=0;j<PointNum;j++){
				b[i][j] = 0;
			}
		}
		b[0][1]=3;
		b[0][3]=4;
		b[1][2]=1;
		b[1][4]=2;
		b[2][4]=7;
		b[3][4]=3;
		b[3][1]=6;
		*/
		int[][] b = {{0,2,0,1,0,0,0},
					 {0,0,0,3,10,0,0},
					 {4,0,0,0,0,5,0},
					 {0,0,2,0,2,8,4},
					 {0,0,0,0,0,0,6},
			  		 {0,0,0,0,0,0,0},
					 {0,0,0,0,0,1,0}};

		Map a = new Map(PointNum);
		a.init(b);
		PathLen qq = a.getPath(0,5);
		System.out.println("len=" + qq.len + "\nPath=" + qq.path.toString());
	}
}


【2】Map.java

//-------java
//This is a class to calculate a map
//Go througth the map and find the shortest way from a to b
//return the path and give the shortest length
//
//Write by Firwood
//2014-09-22
public class Map{
	public final static int MAX = 9999999;
	//saving the numbet of all Point
	int iPointNum;

	//saving the length from start point to [i] 
	int[] rLen;

	//saving the path from start point to [i]
	List[] rList;

	//saving the source length of matrix
	int[][] roads;

	//saving the road of each Point can go to
	List[] RoadListArray;

	//the calculate heap,it's Node is a point number and its 
	//connected point
	PointHeap calcHeap;
	//////////////////////////////////////////////////////////////////////
	public Map(int num){
		//
		iPointNum = num;
		roads= new int[iPointNum][iPointNum];
		rLen = new int[iPointNum];		
		for(int i = 0; i < iPointNum; i++){
			rLen[i] = MAX;			
		}
		rList = new List[iPointNum];
		RoadListArray = new List[iPointNum];
		for(int i=0;i<iPointNum;i++){
			rList[i] = new List();
			RoadListArray[i] = new List();
		}
		calcHeap = new PointHeap();
	}
	public void init(int[][] matrix){
		//
		//transfer matrix to roads, roads is
		//using to save the length of node[i]
		//to node[j]
		for(int i = 0; i < iPointNum; i++){
			for(int j = 0; j < iPointNum; j++){
				if(matrix[i][j] != 0){
					roads[i][j] = matrix[i][j];
				}else{
					if(i != j ){
						roads[i][j] = MAX;
						//this means it is a length which is can't
						//reach
					}else{
						roads[i][j] = 0;
					}
				}
			}
		}
		//
		for(int i = 0; i< iPointNum; i++){
			for(int j= 0; j < iPointNum; j++){
				if(matrix[i][j] != 0){
					RoadListArray[i].push(j);
				}
			}
		}
	}
	public void CalcPath(int endPoint){
		//the result is saving in the rLen(for length) and rList(for the Path)
		while(!calcHeap.isEmpty()){
			//empty means the heap is out
			//every path from the start point is tried
			//finding path is over!!!
		
			HeapNode tempHeapNode = calcHeap.last;
			if(tempHeapNode.toPoint.isEmpty()){
				//empty means the last node can't go any other point
				//should pop this point out, try other point
				calcHeap.pop();
				continue;
			}
			int tempPoint = tempHeapNode.toPoint.pop();
			HeapNode temp = new HeapNode();
			temp.set(tempPoint, RoadListArray[tempPoint]);
			calcHeap.push(temp);
			if(!ShorterPath()){
				//means this path is longer than other found path before
				//there is no need to using this point to brith next point
				//you should use the shorter path
				//pop this point out, to find next
				calcHeap.pop();
				continue;
			}
		}
	}

	public PathLen getPath(int start, int end){
		//begin method for calc the path from start point to the end point
		//
		PathLen thePath = new PathLen();
		
		if(start == end){
			//if the start point is the end point
			//the answer length is 0, and path is not go
			thePath.len = 0;
			thePath.path.push(start);
			return thePath;
		}

		HeapNode startPoint = new HeapNode();
		startPoint.set(start, RoadListArray[start]);
		calcHeap.push(startPoint);
		ShorterPath();
		
		//the real calc all path from the start point
		CalcPath(end);

		//get the needed path result
		thePath.set(rLen[end], rList[end]);
		return thePath;
	}
	public boolean ShorterPath(){
		//using the "calcHeap" to calc is a new shorter path is found
		//if found a new path , using the rList[] to save the path
		//using the rLen[] to saving the length
		//and return true;
		//if the found path is longer than before return false
		HeapNode index = calcHeap.begin.next;
		int a = index.pNum;
		int b = 0;
		int sum = 0;
		index = index.next;
		while(index != calcHeap.end){
			b = index.pNum;
			sum += roads[a][b];
			a = b;
			index = index.next;
		}
		if(sum < rLen[b]){
			rLen[b] = sum;
			rList[b] = calcHeap.getList();
			return true;
		}
		return false;
	}
}
///////////////////////////////////////////////////////////////////////////////////
class PathLen{
	List path;
	int len;
	public PathLen(){
		path = new List();
		len = 0;
	}
	public void set(int num, List setList){
		len = num;
		path = setList.clone();
	}
}


【3】List.java

//----List.java
//Write by Firwood
//2014-09-22
public class List{
	//
	ListNode begin;
	ListNode end;
	public List(){
		begin = new ListNode();
		end = new ListNode();
		begin.next = end;
		end.prev = begin;
	}
	public void push(int num){
		ListNode last = end.prev;

		ListNode temp = new ListNode(num);
		temp.prev = last;
		temp.next = end;

		last.next = temp;
		end.prev = temp;
	}
	public int pop(){
		if(isEmpty()) return 0;
		ListNode temp = end.prev;
		int t = temp.key;
		temp.prev.next = end;
		end.prev = temp.prev;
		return t;
	}
	public boolean isEmpty(){
		return (end.prev == begin);
	}
	public List clone(){
		//
		List temp = new List();
		ListNode p = begin.next;
		while(p != end){
			temp.push(p.key);
			p = p.next;
		}
		return temp;
	}
	public String toString(){
		String str="";
		ListNode index = begin.next;
		while(index != end){
			str += index.key+" ";
			index = index.next;
		}
		return str;
	}
}
class ListNode{
	//
	int key;
	ListNode prev;
	ListNode next;
	public void init(){
		key = 0;
		prev = null;
		next = null;
	}
	public ListNode(){
		init();
	}
	public ListNode(int a){
		init();
		key = a;
	}
}


【4】PointHeap.java

///////-----PointHeap.java
//
//Write by Firwood
//2014-09-22
public class PointHeap{
	//
	HeapNode begin;
	HeapNode end;

	//the last Node of this list,
	//if the list is empty last is the begin
	HeapNode last;

	public PointHeap(){
		begin = new HeapNode();
		last = begin;
		end = new HeapNode();
		begin.next = end;
		end.prev = begin;
	}
	public void push(HeapNode tNode){
		//
		last.next = tNode;
		tNode.prev = last;
		tNode.next = end;
		end.prev = tNode;
		last = tNode;
	}
	public HeapNode pop(){
		if(isEmpty()) return begin;
		HeapNode tNode = last;
		last.prev.next = end;
		end.prev = last.prev;
		last = end.prev;
		return tNode;
	}
	public boolean isEmpty(){
		return (end.prev == begin);
	}
	public List getList(){
		//return a path list from begin point to end point
		List tempList = new List();
		HeapNode a = begin.next;
		while(a != end){
			tempList.push(a.pNum);
			a = a.next;
		}		
		return tempList;
	}

}
////////////////////////
class HeapNode{
	//
	int pNum;
	List toPoint;
	HeapNode prev;
	HeapNode next;
	public void init(){
		pNum = 0;
		toPoint = new List();
		prev = null;
		next = null;
	}
	public HeapNode(){
		init();
	}
	public void set(int num, List ilist){
		pNum = num;
		toPoint = ilist.clone();
	}
}