最短路徑之Dijkstra演算法及例項分析
Dijkstra演算法迪科斯徹演算法
Dijkstra演算法描述為:假設用帶權鄰接矩陣來表示帶權有向圖。首先引進一個輔助向量D,它的每個分量D[i]表示當前所找到的從始點v到每個終點Vi的最短路徑。它的初始狀態為:若兩頂點之間有弧,則D[i]為弧上的權值;否則置D[i]為無窮大。
1. 找到與源點v最近的頂點,並將該頂點併入最終集合S;
2. 根據找到的最近的頂點更新從源點v出發到集合V-S上可達頂點的最短路徑;
3. 重複以上操作。
以前總是認為Dijkstra演算法可以用來求從源點到指定終點的最短路徑,導致總不能抓住演算法的中心思想。現在認為把握Dijkstra的演算法要點為:
1. Dijkstra提出了一個按路徑長度遞增的次序產生最短路徑的演算法;
2. 每次迴圈都可以得到一個從源點到某個頂點的最短路徑,某個即不是確定的一個;
以 帶權有向圖 1為例說明Dijkstra演算法的執行過程:
圖1 帶權有向圖
假設源點為v0,則初始狀態時源點到其它各頂點的距離為:<∽代表無窮大>
源點 終點 |
v1 |
v2 |
v3 |
v4 |
v5 |
v0 |
∽ |
10 |
∽ |
30 |
100 |
由上表可知,與源點v0最近的頂點為v2,距離為10。
將v2加入到最終頂點集合S中。
再根據v2更新從源點到其它頂點的最短距離,即從v0-v2-v3的距離為60<∽,所以將v0到v3的距離更新為60,如下表所示:
源點 終點 |
v1 |
v2 |
v3 |
v4 |
v5 |
v0 |
∽ |
10 |
60 |
30 |
100 |
由上表可知,與源點v0次近的頂點為v4,距離為30。
將v4加入到最終頂點集合S中;
再根據v4更新從源點到其它頂點的最短距離。即從v0-v4-v3的距離為50<60,所以將v0到v3的距離更新為50;從v0-v4-v5的距離為90<100,所以將v0到v5的距離更新為90。
源點 終點 |
v1 |
v2 |
v3 |
v4 |
v5 |
v0 |
∽ |
10 |
50 |
30 |
90 |
重複以上操作……
直到最終集合包含了所有的頂點。
以上參考來源:http://www.cppblog.com/eryar/archive/2013/01/01/196897.html
>>應用例子:深大各地點之最短路徑
#include<iostream>
#include<stack>
#include<string>
#defineM 100
#defineN 100
#definev_num 8 //頂點個數
#definee_num 11 //邊數
usingnamespace std;
classMGraph
{
public:
string name[v_num]; //頂點名稱
string info[v_num]; //頂點資訊
int matrix[N][M]; //鄰接矩陣
int n ; //頂點數
int e ; //邊數
public:
MGraph(int v_n,int e_n){ n = v_n; e =e_n; }
void help();
void buildMap();
void buildInfo();
void display();
void findInfo(int v);
void findDij(int v0,int v);
};
//主選單
voidhelp()
{
cout<<"************************************"<<endl;
cout<<"<1> 查詢景點介紹\n";
cout<<"<2> 查詢任意兩個景點之間的最佳路線\n";
cout<<"<other> 退出\n";
cout<<"************************************"<<endl;
}
//景點距離
voidMGraph::buildMap()
{
matrix[0][1] = 5;
matrix[1][3] = 5;
matrix[1][2] = 8;
matrix[2][3] = 5;
matrix[3][4] = 5;
matrix[4][5] = 4;
matrix[4][6] = 10;
matrix[3][6] = 10;
matrix[5][6] = 10;
matrix[5][7] = 20;
matrix[6][7] = 15;
}
//景點名稱及介紹資訊
voidMGraph::buildInfo()
{
name[0] = "南區";info[0] ="南區有學生宿舍以及新建的信工,機電,醫學院大樓";
name[1] = "學生活動中心/石頭塢"; info[1] = "各種學生活動的主要場所";
name[2] = "南圖";info[2] = "南圖書館與北圖書館相對而立,主要存放理工科類書籍";
name[3] = "教學樓";info[3] ="顧名思義,很多課程都在這上,建築呈之字形,分A,B,C,D四棟";
name[4] = "北圖";info[4] ="北圖書館文學氣息濃厚,主要存放文科類書籍";
name[5] = "辦公樓";info[5] ="深圳大學的行政辦公樓";
name[6] = "科技樓";info[6] ="又被稱為中指樓,深大最具特色的建築,兼具辦公,科研";
name[7] = "文科樓";info[7] ="文科樓是深大學生主要上課的場所之一";
}
//顯示景點
voidMGraph::display()
{
int i;
cout<<"*******************************選單**********************************"<<endl;
cout<<"*********************************************************************"<<endl;
cout<<"<0>返回上層選單 ";
for(i=0;i<v_num;++i)
{
if((i+2)%3==0)
{
cout<<'<'<<i+1<<'>'<<name[i]<<endl;
cout<<"---------------------------------------------------------------------"<<endl;
}
else
cout<<'<'<<i+1<<'>'<<name[i]<<" ";
}
cout<<endl;
cout<<"*********************************************************************"<<endl<<endl;
}
//查詢景點資訊
voidMGraph::findInfo(int v)
{
cout<<"-------------------------<"<<name[v]<<">------------------------------"<<endl;
cout<<endl;
cout<<info[v]<<endl;
cout<<"---------------------------------------------------------------------"<<endl;
cout<<endl<<endl;
}
//最短路徑演算法
voidMGraph::findDij(int v0,int v) //v0表示源頂點
{
int *dist=(int *)malloc(sizeof(int)*n);
int *path=(int *)malloc(sizeof(int)*n);
int i,j,k;
bool *visited=(bool*)malloc(sizeof(bool)*n);
for(i=0;i<n;i++) //初始化
{
if(matrix[v0][i]>0&&i!=v0)
{
dist[i]=matrix[v0][i];
path[i]=v0; //path記錄最短路徑上從v0到i的前一個頂點
}
else
{
dist[i]=INT_MAX; //若i不與v0直接相鄰,則權值置為無窮大
path[i]=-1;
}
visited[i]=false;
path[v0]=v0;
dist[v0]=0;
}
visited[v0]=true;
for(i=1;i<n;i++) //迴圈擴充套件n-1次
{
int min=INT_MAX;
int u;
for(j=0;j<n;j++) //尋找未被擴充套件的權值最小的頂點
{
if(visited[j]==false&&dist[j]<min)
{
min=dist[j];
u=j;
}
}
visited[u]=true;
for(k=0;k<n;k++) //更新dist陣列的值和路徑的值
{
if(visited[k]==false&&matrix[u][k]>0&&min+matrix[u][k]<dist[k])
{
dist[k]=min+matrix[u][k];
path[k]=u;
}
}
}
//輸出最短路線
cout<<endl<<name[v0]<<"到"<<name[v]<<"的最短路徑是:"<<dist[v]<<endl;
//列印路線
stack<int> s;
int u=v;
while(v!=v0)
{
s.push(v);
v=path[v];
}
s.push(v);
cout<<"具體路線為:";
while(!s.empty())
{
cout<<name[s.top()]<<"";
s.pop();
}
cout<<endl<<endl;
}
//主函式
intmain(int argc, char *argv[])
{
int i,j,c2;
char c1;
MGraph g(v_num,e_num);
int v0,v;
for(i=0;i<N;i++)
for(j=0;j<M;j++)
g.matrix[i][j]=10000;
g.buildInfo();
g.buildMap();
do
{
help();
cout<<"請選擇查詢內容:"<<endl;
cin>>c1;
switch(c1)
{
case'1':while(1)
{
g.display();
cout<<"請輸入查詢景點編號:"<<endl;
cin>>c2;
if(c2==0) break;
g.findInfo(c2-1);
}
break;
case'2':while(1)
{
g.display();
cout<<"請依次輸入兩個查詢景點編號(第一個編號小於第二個):"<<endl;
cin>>v0>>v;
if(v0==0||v==0) break;
g.findDij(v0-1,v-1);
}
break;
}
}while(c1=='1'||c1=='2');
return 0;
}
相關推薦
最短路徑之Dijkstra演算法及例項分析
Dijkstra演算法迪科斯徹演算法 Dijkstra演算法描述為:假設用帶權鄰接矩陣來表示帶權有向圖。首先引進一個輔助向量D,它的每個分量D[i]表示當前所找到的從始點v到每個終點Vi的最短路徑。它的初始狀態為:若兩頂點之間有弧,則D[i]為弧上的權值;否則置D[i]為無
A.pro讀演算法の11:最短路徑之Dijkstra演算法
此文是獻給OIer看的。講的東西比較基礎(其實我理解Dijkstra花了很長時間)。NOIP2018結束約有1個月了,但是我們仍要繼續前進,為NOIP2019做準備。本節學習Dijkstra的演算法思想和實現,以及優先佇列和堆優化。線段樹也可以做到優化,甚至可能還更快,但是我太弱了不會。。
最短路徑之Dijkstra演算法
Dijkstra(迪傑斯特拉)演算法是典型的最短路徑路由演算法,用於計算一個節點到其他所有節點的最短路徑。主要特點是以起始點為中心向外層層擴充套件,直到擴充套件到終點為止(BFS、prime演算法都有類似思想)。Dijkstra演算法能得出最短路徑的最優解,但由於它遍歷計算
最短路徑之Dijkstra演算法 C語言實現
Dijkstra演算法(單源點路徑演算法,要求:圖中不存在負權值邊): 步驟: a. 初始時,S只包含源點,即S={v},v的距離為0。U包含除v外的其他頂點,即: U={其餘頂點},若v與U中頂點u有邊,則u的距離設定為相應的權值,若u v之間不存在邊,則
【演算法導論】單源最短路徑之Dijkstra演算法
Dijkstra演算法解決了有向圖上帶正權值的單源最短路徑問題,其執行時間要比Bellman-Ford演算法低,但適用範圍比Bellman-Ford演算法窄。 迪傑斯特拉提出的按路徑長度遞增次序來產生源點到各頂點的最短路徑的演算法思想是:對有n個頂點的有向連
最短路徑之Dijkstra演算法的概念與實現
基本概念 要找出最短路徑,其實就是從起點遍歷所有能到達的頂點,然後計算他們的權重。Dijkstra演算法核心在於邊的鬆弛(relax),可以想象成一根繃緊的橡皮筋,讓它放鬆下來。即是計算源點(s)經過當前點(v)到目標點(w)的權重,如果比目標點(w)之前的權
最短路徑之Dijkstra演算法Java實現
Dijkstra演算法步驟 以下圖為例,求頂點v1到其他頂點的最短路徑 初始化dis陣列,怎麼初始化呢?v1→v1設定為0,不能直接到達的設定為無窮大,能直接到達的附權值,並且定義集合T,初始
最短路徑之Dijkstra演算法思想講解
1 最短路徑演算法 在日常生活中,我們如果需要常常往返A地區和B地區之間,我們最希望知道的可能是從A地區到B地區間的眾多路徑中,那一條路徑的路途最短。最短路徑問題是圖論研究中的一個經典演算法問題, 旨在尋找圖(由結點和路徑組成的)中兩結點之間的最短路徑。 演算法具體的
演算法筆記--最短路徑之dijkstra演算法
1 最短路徑演算法 在日常生活中,我們如果需要常常往返A地區和B地區之間
資料結構之---C語言實現最短路徑之Dijkstra(迪傑斯特拉)演算法
此處共有兩段程式碼: 一、 這段程式碼比較全面,其中參考了github上的相關原始碼。可以說功能強大。 //Dijkstra(迪傑斯特拉演算法) #include <stdio.h> #include <stdlib.h> #include <
最短路徑之Dijkstra(迪傑斯特拉)演算法(無向圖)
簡介 Dijkstra(迪傑斯特拉)演算法是典型的單源最短路徑演算法,用於計算一個節點到其他所有節點的最短路徑。主要特點是以起始點為中心向外層層擴充套件,直到擴充套件到終點為止。由for迴圈可知,其
結點對最短路徑之Floyd演算法原理詳解及實現
上兩篇部落格介紹了計算單源最短路徑的Bellman-Ford演算法和Dijkstra演算法。Bellman-Ford演算法適用於任何有向圖,即使圖中包含負環路,它還能報告此問題。Dijkstra演算法執行速度比Bellman-Ford演算法要快,但是其要求圖中不能包含負權重
最短路徑之Dijkstra算法
最優解 bubuko 原來 body table 特點 修改 ble mil Dijkstra(迪傑斯特拉)算法是典型的最短路徑路由算法,用於計算一個節點到其他所有節點的最短路徑。主要特點是以起始點為中心向外層層擴展,直到擴展到終點為止。Dijkstra算法能得出最短路
單元最短路徑問題---Dijkstra演算法
最短路徑—Dijkstra演算法和Floyd演算法(理解):https://blog.csdn.net/m0_37345402/article/details/76695930 理解最短路徑——迪傑斯特拉(dijkstra)演算法:https://www.cnblogs.com/iambupu/
最短路徑問題---Dijkstra演算法詳解
前言 Nobody can go back and start a new beginning,but anyone can start today and make a new ending. Name:Willam Time:2017/3/8 1、最短路徑問題介紹
最短路徑問題-Dijkstra演算法
前言: 最短路徑演算法用於計算一個節點到其他所有節點的最短路徑。主要特點是以起始點為中心向外層層擴充套件,直到擴充套件到終點為止。 最短路徑問題是圖論研究中的一個經典演算法問題,是尋找圖(由結點和路徑組成的)中兩結點之間的最短路徑。 文章為了通俗易懂,避免使用一些複雜詞
Java資料結構:單源最短路徑問題---Dijkstra演算法
嚶擊長空 如圖: 思路:先任意找一個根節點,然後開始迴圈找連線該點所有邊,然後找到權值最小的一項,標記被訪問,然後再次迴圈找除了根節點和被訪問過的結點的邊,找到權值最小的。具體開註釋,非常詳細喲。 上程式碼: public void shortesPath(int i) { in
資料結構與演算法--最短路徑之Floyd演算法
一、解決單源最短路徑問題的Dijkstra演算法 我們知道Dijkstra演算法只能解決單源最短路徑問題,且要求邊上的權重都是非負的。那麼有沒有辦法解決任意起點到任意頂點的最短路徑問題呢?如果用Dijkstra演算法,可以這樣做: Dijkstra[]
最短路徑 之 SPFA演算法
http://hi.baidu.com/southhill/item/ab26a342590a5aae60d7b967 求最短路徑的演算法有許多種,除了排序外,恐怕是OI界中解決同一類問題演算法最多的了。最熟悉的無疑是Dijkstra,接著是Bellman-Ford,它們都可以求出由一個源點向其他各點的
圖結構練習——最短路徑(Dijkstra演算法)
think: 1注意重複邊的覆蓋 2注意map陣列的初始化 3注意dist陣列的初始化 圖結構練習——最短路徑 Time Limit: 1000MS Memory Limit: 65536KB Problem Description 給定一個