(前幾天並多少時間,現在補充一下!)下面是原始的dijkstra算法:
public static void dijkstra(int v,float[][] a, flaot[] dist,int[] prev)
{
int n=dist.length-1;
if(v<1||v>n)return;
boolean[] s = new boolean[n+1];
//此處的循環是初始化
for(int i=1; i<=n; i++)
{
dis[i]=a[v][i];
s[i]= false;
if(dist[i]==Float.MAX_VALUE)prev[i]=0;
else prev[i]=v;
}
//此處開始遍歷
dist[v]=0; s[v]=true;
//該循環是求的所有節點到源節點的路徑,每循環一次求的一個節點到源節點的距離
for(int i=1; i<n; i++)
{
float temp = Float.MAX_VALUE;
int u=v;
//shortestPath(此處取該循環爲shortestPath)
for(int j=1; j<n; j++)
{
if((!s[j])&&(dist[j]<temp))
{
u=j;
temp=dist[j];
}
}
s[u]=true;
//updateDist(取名爲updateDist)
for(int j=1; j<n; j++)
{
if((!s[j])&&(a[u][j]<Float.MAX.VALUE))
{
float newdist = dist[u]+a[u][j];
if(newdist<dist[j])
{
dist[j]=newdist;
prev[j]=u;
}
}
}
}
}
以前看過Dijkstra算法,但是一直沒有深入的研究它!最近由於項目的需要,所以今天研究了一下!下面介紹一下這個算法幾個重要的幾點!
其實這個算法有兩個比較重要的地方!在書上開始有一個循環,是對參數初始化。這個就沒必要研究了!主要的是第二個循環裏面的兩個循環,第二個循環要進行n-1次(也就是循環節點個數減去源節點),這就是要取得其他節點到源節點的距離,一次循環就是取得一個節點到源節點的距離。那麼在第二個循環裏面的第一個循環(這裏叫該循環爲shortestPath)就是取得當前能夠到達源節點最短的節點,並且該節點是未被訪問過的節點。取得在未被訪問的節點裏面到源節點最短路徑的節點u後,最一個循環就是修改和u節點相連的節點到源節點的距離(這裏稱該循環爲updateDist),我這裏稱這一步爲更新u的鄰接節點到源節點的距離。再回到shortestPath循環,就有可能取到u的鄰接節點。下面我談談對這個算法的改進。
我們知道在shortestPath循環中,在書上的源碼都是要遍歷圖中所有的節點,這樣我覺得存在極大的浪費,我們知道該步是取得在dis數組中到源節點最短的節點,並且該節點是未被訪問過的,所以這裏根本沒必要遍歷圖中所有的節點,只需遍歷dis數組中的節點,而且我們知道dist的新的距離都是通過updateDist循環得到的,所以我們完全可以將dist數組裏的距離存儲到一個集合中,我們可以自定義一個集合,當我們每次想該集合添加元素(也就是到源節點的距離)的時候自動對該集合中進行排序,進行遞增排序,我們取該集合的第一個元素就是當前到源節點最短的節點,並且該節點是未被訪問的,取出時並將該節點從該集合中移出。這樣我們就省掉了shortestPath這個循環了,這樣對算法的運行將有極大的提高!還有就是後面的updateDist循環,在書上的源碼中也是對圖中的所有節點進行遍歷,其實也沒必要,只需對u的領結節點遍歷即使!這樣有省掉了沒必要的循環,這樣的Dijkstra算法,我相信應該不會很慢!
注意的是這種優化也需要對你的圖結構進行優化,具體的優化可以見本博客的《新穎的圖存儲結構【看來之後你會對圖的結構有新的想法】》文章,裏面有詳細講解一種圖的存儲結構!
下面貼出我改進的算法:
public class ShortestPathIterator_3 {
private Graph graph;
private boolean visited[];
private int prev[];
private int source;
private int position;
private float pathCost[];
private int n;
private Map<Integer,Float> visitable;
//獲得當前的源節點
public int getSource()
{
return this.source;
}
public ShortestPathIterator_3(Graph graph,int source)
{
visited = new boolean[graph.getNode_Count()];
this.visitable = new HashMap<Integer,Float>();
prev = new int[graph.getNode_Count()];
this.graph = graph;
this.source = source;
this.pathCost = new float[this.graph.getNode_Count()];
for(int i=0; i<graph.getNode_Count(); i++)
{
this.pathCost[i]=Float.MAX_VALUE;
this.visited[i]=false;
}
EdgeIterator edgeIterator = graph.getEdgeIterator(this.source);//獲得所有和元節點相鄰的節點集合
int adjancentNode;
while(edgeIterator.hasNext())
{
adjancentNode = this.graph.getAdjancentNode(edgeIterator.next());
this.pathCost[adjancentNode] = this.graph.getEdgePrestige(edgeIterator.next());
this.visitable.put(adjancentNode, this.graph.getEdgePrestige(edgeIterator.next()));
this.prev[adjancentNode] = this.source;
}
this.visited[this.source]=true;
this.position=0;
this.n=this.graph.getNode_Count()-1;
}
public int getNext()
{
Integer u = this.source;
if(this.position<=this.n-1)
{
float temp = Float.MAX_VALUE;
Iterator<Integer> keyIterator = this.visitable.keySet().iterator();
int next;
//取得未被訪問並且,到源點最短的節點,並賦值給U,同時將和U相連的節點到源點的距離進行更新
while(keyIterator.hasNext())
{
next= keyIterator.next();
if(this.visitable.get(next)<temp)
{
u=next;
temp = this.visitable.get(next);
}
}
this.visited[u]=true;
//更新和u相連的節點到源點的距離
updatePathCost(u);
this.visitable.remove(u);
this.position++;
return u;
}
else
{
return -1;
}
}
public void updatePathCost(int u)
{
float newPathCost;
EdgeIterator edgeIterator = this.graph.getEdgeIterator(u);//獲得所有和u節點相鄰的節點集合
int adjancentNode;
while(edgeIterator.hasNext())
{
adjancentNode = this.graph.getAdjancentNode(edgeIterator.next());
//將還未被訪問的節點進行判斷到源點的距離
if(!this.visited[adjancentNode])
{
newPathCost = this.getPathCost(u)+this.graph.getEdgePrestige(this.graph.getEdgeId(adjancentNode, u));
if(newPathCost<this.getPathCost(adjancentNode))
{
this.visitable.put(new Integer(adjancentNode), newPathCost);
this.pathCost[adjancentNode] = newPathCost;
this.prev[adjancentNode]=u;
}
}
}
}
public float getPathCost(int node)
{
return this.pathCost[node];
}
public int getPrevNode(int node)
{
return this.prev[node];
}
}
這個優化我已經實現了!需要深入探討的可以和我聯繫。希望能夠幫助和我以前一樣的人!謝謝瀏覽!