最短路徑算法

最短路徑算法在現(xiàn)實(shí)生活中也具有非常多的應(yīng)用,例如在一個(gè)復(fù)雜的景區(qū)棕洋,想要從一個(gè)景點(diǎn)到另外一個(gè)景點(diǎn)遂庄,利用最短路徑算法就可以找到最短的路程,而如果不做規(guī)劃就隨緣前往塔拳,可能會(huì)繞很多路才能到達(dá)鼠证,雖然到了,但是精力都花費(fèi)在走路上了靠抑,更別說去觀光景點(diǎn)了名惩。
  • Dijkstra算法
    • 算法思想分析
      算法從一個(gè)點(diǎn)開始,向周圍擴(kuò)散孕荠,每次去尋找一個(gè)確定了最短路徑的點(diǎn)娩鹉,并且同時(shí)更新所有點(diǎn)的最短路徑距離,直到所有點(diǎn)都被找到最短路徑
    • 算法具體代碼
#define MAX    100
#define INF    32767
int tempMatrix[MAX][MAX]; // 鄰接矩陣
int mVexNum; // 頂點(diǎn)數(shù)量
void dijkstra(int start, int prev[], int dist[])
{
    int i,j,k = 0;
    int min;
    int tmp;
    int flag[MAX];      // flag[i] = 1 表示"頂點(diǎn)vs"到"頂點(diǎn)i"的最短路徑已成功獲取稚伍。
    
    // 初始化
    for (i = 0; i < mVexNum; i++)
    {
        flag[i] = 0;              // 頂點(diǎn)i的最短路徑還沒獲取到弯予。
        prev[i] = 0;              // 頂點(diǎn)i的前驅(qū)頂點(diǎn)為0。
        dist[i] = tempMatrix[start][i]; // 頂點(diǎn)i的最短路徑為"頂點(diǎn)start"到"頂點(diǎn)i"的權(quán)个曙。
    }
    
    // 對(duì)"頂點(diǎn)start"自身進(jìn)行初始化
    flag[start] = 1;
    dist[start] = 0;
    
    // 遍歷mVexNum-1次锈嫩;每次找出一個(gè)頂點(diǎn)的最短路徑。
    for (i = 1; i < mVexNum; i++)
    {
        // 尋找當(dāng)前最小的路徑垦搬;
        // 即呼寸,在未獲取最短路徑的頂點(diǎn)中,找到離start最近的頂點(diǎn)(k)猴贰。
        min = INF;
        for (j = 0; j < mVexNum; j++)
        {
            if (flag[j] == 0 && dist[j] < min)
            {
                min = dist[j];
                k = j;
            }
        }
        // 標(biāo)記"頂點(diǎn)k"為已經(jīng)獲取到最短路徑
        flag[k] = 1;
        
        // 修正當(dāng)前最短路徑和前驅(qū)頂點(diǎn)
        // 即对雪,當(dāng)已經(jīng)知道"頂點(diǎn)k的最短路徑"之后,更新"未獲取最短路徑的頂點(diǎn)的最短路徑和前驅(qū)頂點(diǎn)"米绕。
        for (j = 0; j < mVexNum; j++)
        {
            tmp = (tempMatrix[k][j] == INF ? INF : (min + tempMatrix[k][j]));
            if (flag[j] == 0 && (tmp  < dist[j]))
            {
                dist[j] = tmp;
                prev[j] = k;
            }
        }
    }
}
  • 算法細(xì)節(jié)分析
    算法中用到了三個(gè)數(shù)組瑟捣,分別是:

    • prev [ ]:用來存儲(chǔ)每個(gè)節(jié)點(diǎn)的前驅(qū)節(jié)點(diǎn)
    • dist [ ]:用來存儲(chǔ)每個(gè)節(jié)點(diǎn)的最短路徑距離
    • flag [ ]:輔助數(shù)組,用來存儲(chǔ)每個(gè)節(jié)點(diǎn)是否已經(jīng)找到了最短路徑

    算法中用到了三次循環(huán)栅干,分別是:

    • 第一次:循環(huán)了N-1次迈套,目的是每次循環(huán)都找到一個(gè)節(jié)點(diǎn)的最短路徑
    • 第二次:循環(huán)了N次,目的是找到目前距離起始點(diǎn)最近的點(diǎn)碱鳞,然后標(biāo)記為已經(jīng)找到最短路徑
    • 第三次:循環(huán)了N次桑李,由于新加入了一個(gè)確定了最短路徑的節(jié)點(diǎn),那么原來的節(jié)點(diǎn)的最短路徑將有可能被更新窿给,所以這個(gè)循環(huán)的目的就是更新所有的節(jié)點(diǎn)的最短路徑的距離贵白,如果發(fā)現(xiàn)了更短路徑,同時(shí)也會(huì)將前驅(qū)節(jié)點(diǎn)更新

    回首在最小生成樹算法中的Prim算法填大,這兩者的過程十分相似戒洼,那兩者的差別點(diǎn)在哪里呢?

  • 與Prim算法的相同點(diǎn)和不同點(diǎn)

    • 相同點(diǎn)
      1. prev [ ] 數(shù)組和flag [ ] 數(shù)組是一樣的允华,在兩個(gè)算法中均有一個(gè)用來存儲(chǔ)前驅(qū)節(jié)點(diǎn)的數(shù)組圈浇,目的是為了在算法進(jìn)行完之后將路徑打印出來,另外一個(gè)用來存儲(chǔ)每個(gè)節(jié)點(diǎn)是否被確定靴寂。
      2. 有兩次循環(huán)是一樣的磷蜀,第一次循環(huán)都是為了每次確定一個(gè)點(diǎn),最后一次循環(huán)百炬,也都是因?yàn)橛行碌狞c(diǎn)被確定了褐隆,所以需要更新其他節(jié)點(diǎn)的狀態(tài)
    • 不同點(diǎn)
      1. 在Dijkstra算法中使用一個(gè)數(shù)組來存儲(chǔ)每個(gè)節(jié)點(diǎn)的最短路徑距離,而在Prim算法中使用一個(gè)數(shù)組來存儲(chǔ)節(jié)點(diǎn)到最小生成樹中的節(jié)點(diǎn)的最短距離
      2. 在Dijkstra算法中的第二個(gè)循環(huán)是來找目前離起始點(diǎn)最短距離的點(diǎn)剖踊,而在Prim算法中的第二個(gè)循環(huán)是用來找目前離最小生成樹中的節(jié)點(diǎn)距離最近的點(diǎn)
  • Floyd算法

    • 算法思想分析
      Floyd算法的過程建立在一個(gè)矩陣中庶弃,這個(gè)矩陣存儲(chǔ)的是各個(gè)點(diǎn)之間的距離衫贬,對(duì)于每個(gè)點(diǎn)進(jìn)行一次循環(huán),這個(gè)循環(huán)過程中做的事情就是去尋找通過該節(jié)點(diǎn)的邊是否小于原本存儲(chǔ)在矩陣中的值歇攻,如果小于固惯,則更新
    • 算法的具體代碼
#define MAX    100
#define INF    32767
int mVexNum;             // 頂點(diǎn)數(shù)
int mMatrix[MAX][MAX];   // 鄰接矩陣
void floyd(int path[][MAX], int dist[][MAX])
{
    int i,j,k;
    int tmp;
    
    // 初始化
    for (i = 0; i < mVexNum; i++)
    {
        for (j = 0; j < mVexNum; j++)
        {
            dist[i][j] = mMatrix[i][j];    // "頂點(diǎn)i"到"頂點(diǎn)j"的路徑長(zhǎng)度為"i到j(luò)的權(quán)值"。
            path[i][j] = j;                // "頂點(diǎn)i"到"頂點(diǎn)j"的最短路徑是經(jīng)過頂點(diǎn)j缴守。
        }
    }
    
    // 計(jì)算最短路徑
    for (k = 0; k < mVexNum; k++)
    {
        for (i = 0; i < mVexNum; i++)
        {
            for (j = 0; j < mVexNum; j++)
            {
                // 如果經(jīng)過下標(biāo)為k頂點(diǎn)路徑比原兩點(diǎn)間路徑更短葬毫,則更新dist[i][j]和path[i][j]
                tmp = (dist[i][k]==INF || dist[k][j]==INF) ? INF : (dist[i][k] + dist[k][j]);
                if (dist[i][j] > tmp)
                {
                    // "i到j(luò)最短路徑"對(duì)應(yīng)的值設(shè),為更小的一個(gè)(即經(jīng)過k)
                    dist[i][j] = tmp;
                    // "i到j(luò)最短路徑"對(duì)應(yīng)的路徑屡穗,經(jīng)過k
                    path[i][j] = path[i][k];
                }
            }
        }
    }
}
  • 算法的細(xì)節(jié)分析
    算法中用到了兩個(gè)數(shù)組:

    • dist [ ]:這個(gè)二維數(shù)組用來存儲(chǔ)兩個(gè)節(jié)點(diǎn)之間的最短路徑距離
    • path [ ]:這個(gè)數(shù)組用來存儲(chǔ)兩個(gè)節(jié)點(diǎn)之間的最短路徑將會(huì)經(jīng)過的點(diǎn)贴捡,目的是用來存儲(chǔ)最短路徑

    算法中用到了三次循環(huán):

    • 第一次循環(huán):第一次循環(huán)N次,對(duì)于每個(gè)點(diǎn)都需要進(jìn)行更新表的操作
    • 第二次循環(huán)和第三次循環(huán):這兩次循環(huán)實(shí)際上是對(duì)矩陣的一個(gè)遍歷操作
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末村砂,一起剝皮案震驚了整個(gè)濱河市烂斋,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌箍镜,老刑警劉巖源祈,帶你破解...
    沈念sama閱讀 222,252評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異色迂,居然都是意外死亡香缺,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門歇僧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來图张,“玉大人,你說我怎么就攤上這事诈悍』雎郑” “怎么了?”我有些...
    開封第一講書人閱讀 168,814評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵侥钳,是天一觀的道長(zhǎng)适袜。 經(jīng)常有香客問我,道長(zhǎng)舷夺,這世上最難降的妖魔是什么苦酱? 我笑而不...
    開封第一講書人閱讀 59,869評(píng)論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮给猾,結(jié)果婚禮上疫萤,老公的妹妹穿的比我還像新娘。我一直安慰自己敢伸,他們只是感情好扯饶,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,888評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般尾序。 火紅的嫁衣襯著肌膚如雪钓丰。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,475評(píng)論 1 312
  • 那天每币,我揣著相機(jī)與錄音斑粱,去河邊找鬼。 笑死脯爪,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的矿微。 我是一名探鬼主播痕慢,決...
    沈念sama閱讀 41,010評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼涌矢!你這毒婦竟也來了掖举?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,924評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤娜庇,失蹤者是張志新(化名)和其女友劉穎塔次,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體名秀,經(jīng)...
    沈念sama閱讀 46,469評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡励负,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,552評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了匕得。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片继榆。...
    茶點(diǎn)故事閱讀 40,680評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖汁掠,靈堂內(nèi)的尸體忽然破棺而出略吨,到底是詐尸還是另有隱情,我是刑警寧澤考阱,帶...
    沈念sama閱讀 36,362評(píng)論 5 351
  • 正文 年R本政府宣布翠忠,位于F島的核電站,受9級(jí)特大地震影響乞榨,放射性物質(zhì)發(fā)生泄漏秽之。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,037評(píng)論 3 335
  • 文/蒙蒙 一姜凄、第九天 我趴在偏房一處隱蔽的房頂上張望政溃。 院中可真熱鬧,春花似錦态秧、人聲如沸董虱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽愤诱。三九已至云头,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間淫半,已是汗流浹背溃槐。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評(píng)論 1 274
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留科吭,地道東北人昏滴。 一個(gè)月前我還...
    沈念sama閱讀 49,099評(píng)論 3 378
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像对人,于是被迫代替她去往敵國(guó)和親谣殊。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,691評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容