亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C > 正文

floyd算法實現思路及實例代碼

2020-01-26 15:38:00
字體:
來源:轉載
供稿:網友

正如我們所知道的,Floyd算法用于求最短路徑。Floyd算法可以說是Warshall算法的擴展,三個for循環就可以解決問題,所以它的時間復雜度為O(n^3)。

Floyd算法的基本思想如下:從任意節點A到任意節點B的最短路徑不外乎2種可能,1是直接從A到B,2是從A經過若干個節點X到B。所以,我們假設Dis(AB)為節點A到節點B的最短路徑的距離,對于每一個節點X,我們檢查Dis(AX) + Dis(XB) < Dis(AB)是否成立,如果成立,證明從A到X再到B的路徑比A直接到B的路徑短,我們便設置Dis(AB) = Dis(AX) + Dis(XB),這樣一來,當我們遍歷完所有節點X,Dis(AB)中記錄的便是A到B的最短路徑的距離。

很簡單吧,代碼看起來可能像下面這樣:

復制代碼 代碼如下:

for ( int i = 0; i < 節點個數; ++i )
{
    for ( int j = 0; j < 節點個數; ++j )
    {
        for ( int k = 0; k < 節點個數; ++k )
        {
            if ( Dis[i][k] + Dis[k][j] < Dis[i][j] )
            {
                // 找到更短路徑
                Dis[i][j] = Dis[i][k] + Dis[k][j];
            }
        }
    }
}

但是這里我們要注意循環的嵌套順序,如果把檢查所有節點X放在最內層,那么結果將是不正確的,為什么呢?因為這樣便過早的把i到j的最短路徑確定下來了,而當后面存在更短的路徑時,已經不再會更新了。

讓我們來看一個例子,看下圖:

圖中紅色的數字代表邊的權重。如果我們在最內層檢查所有節點X,那么對于A->B,我們只能發現一條路徑,就是A->B,路徑距離為9。而這顯然是不正確的,真實的最短路徑是A->D->C->B,路徑距離為6。造成錯誤的原因就是我們把檢查所有節點X放在最內層,造成過早的把A到B的最短路徑確定下來了,當確定A->B的最短路徑時Dis(AC)尚未被計算。所以,我們需要改寫循環順序,如下:

復制代碼 代碼如下:

for ( int k = 0; k < 節點個數; ++k )
{
    for ( int i = 0; i < 節點個數; ++i )
    {
        for ( int j = 0; j < 節點個數; ++j )
        {
            if ( Dis[i][k] + Dis[k][j] < Dis[i][j] )
            {
                // 找到更短路徑
                Dis[i][j] = Dis[i][k] + Dis[k][j];
            }
        }
    }
}

這樣一來,對于每一個節點X,我們都會把所有的i到j處理完畢后才繼續檢查下一個節點。

那么接下來的問題就是,我們如何找出最短路徑呢?這里需要借助一個輔助數組Path,它是這樣使用的:Path(AB)的值如果為P,則表示A節點到B節點的最短路徑是A->...->P->B。這樣一來,假設我們要找A->B的最短路徑,那么就依次查找,假設Path(AB)的值為P,那么接著查找Path(AP),假設Path(AP)的值為L,那么接著查找Path(AL),假設Path(AL)的值為A,則查找結束,最短路徑為A->L->P->B。

那么,如何填充Path的值呢?很簡單,當我們發現Dis(AX) + Dis(XB) < Dis(AB)成立時,就要把最短路徑改為A->...->X->...->B,而此時,Path(XB)的值是已知的,所以,Path(AB) = Path(XB)。

好了,基本的介紹完成了,接下來就是實現的時候了,這里我們使用圖以及鄰接矩陣:

復制代碼 代碼如下:

#define INFINITE 1000           // 最大值
#define MAX_VERTEX_COUNT 20   // 最大頂點個數
//////////////////////////////////////////////////////////////////////////

struct Graph
{
    int     arrArcs[MAX_VERTEX_COUNT][MAX_VERTEX_COUNT];    // 鄰接矩陣
    int     nVertexCount;                                 // 頂點數量
    int     nArcCount;                                    // 邊的數量
};
//////////////////////////////////////////////////////////////////////////
首先,我們寫一個方法,用于讀入圖的數據:

void readGraphData( Graph *_pGraph )
{
    std::cout << "請輸入頂點數量和邊的數量: ";
    std::cin >> _pGraph->nVertexCount;
    std::cin >> _pGraph->nArcCount;

    std::cout << "請輸入鄰接矩陣數據:" << std::endl;
    for ( int row = 0; row < _pGraph->nVertexCount; ++row )
    {
        for ( int col = 0; col < _pGraph->nVertexCount; ++col )
        {
            std::cin >> _pGraph->arrArcs[row][col];
        }
    }
}

接著,就是核心的Floyd算法:

復制代碼 代碼如下:

void floyd( int _arrDis[][MAX_VERTEX_COUNT], int _arrPath[][MAX_VERTEX_COUNT], int _nVertexCount )
{
    // 先初始化_arrPath
    for ( int i = 0; i < _nVertexCount; ++i )
    {
        for ( int j = 0; j < _nVertexCount; ++j )
        {
            _arrPath[i][j] = i;
        }
    }
    //////////////////////////////////////////////////////////////////////////

    for ( int k = 0; k < _nVertexCount; ++k )
    {
        for ( int i = 0; i < _nVertexCount; ++i )
        {
            for ( int j = 0; j < _nVertexCount; ++j )
            {
                if ( _arrDis[i][k] + _arrDis[k][j] < _arrDis[i][j] )
                {
                    // 找到更短路徑
                    _arrDis[i][j] = _arrDis[i][k] + _arrDis[k][j];

                    _arrPath[i][j] = _arrPath[k][j];
                }
            }
        }
    }
}

OK,最后是輸出結果數據代碼:
復制代碼 代碼如下:

void printResult( int _arrDis[][MAX_VERTEX_COUNT], int _arrPath[][MAX_VERTEX_COUNT], int _nVertexCount )
{
    std::cout << "Origin -> Dest   Distance    Path" << std::endl;

    for ( int i = 0; i < _nVertexCount; ++i )
    {
        for ( int j = 0; j < _nVertexCount; ++j )
        {
            if ( i != j )   // 節點不是自身
            {
                std::cout << i+1 << " -> " << j+1 << "/t/t";
                if ( INFINITE == _arrDis[i][j] )    // i -> j 不存在路徑
                {
                    std::cout << "INFINITE" << "/t/t";
                }
                else
                {
                    std::cout << _arrDis[i][j] << "/t/t";

                    // 由于我們查詢最短路徑是從后往前插,因此我們把查詢得到的節點
                    // 壓入棧中,最后彈出以順序輸出結果。
                    std::stack<int> stackVertices;
                    int k = j;

                    do
                    {
                        k = _arrPath[i][k];
                        stackVertices.push( k );
                    } while ( k != i );
                    //////////////////////////////////////////////////////////////////////////

                    std::cout << stackVertices.top()+1;
                    stackVertices.pop();

                    unsigned int nLength = stackVertices.size();
                    for ( unsigned int nIndex = 0; nIndex < nLength; ++nIndex )
                    {
                        std::cout << " -> " << stackVertices.top()+1;
                        stackVertices.pop();
                    }

                    std::cout << " -> " << j+1 << std::endl;
                }
            }
        }
    }
}

好了,是時候測試了,我們用的圖如下:

測試代碼如下:

復制代碼 代碼如下:

int main( void )
{
    Graph myGraph;
    readGraphData( &myGraph );
    //////////////////////////////////////////////////////////////////////////

    int arrDis[MAX_VERTEX_COUNT][MAX_VERTEX_COUNT];
    int arrPath[MAX_VERTEX_COUNT][MAX_VERTEX_COUNT];

    // 先初始化arrDis
    for ( int i = 0; i < myGraph.nVertexCount; ++i )
    {
        for ( int j = 0; j < myGraph.nVertexCount; ++j )
        {
            arrDis[i][j] = myGraph.arrArcs[i][j];
        }
    }

    floyd( arrDis, arrPath, myGraph.nVertexCount );
    //////////////////////////////////////////////////////////////////////////

    printResult( arrDis, arrPath, myGraph.nVertexCount );
    //////////////////////////////////////////////////////////////////////////

    system( "pause" );
    return 0;
}

如圖:

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
在线视频欧美日韩精品| 欧美另类极品videosbestfree| 亚洲经典中文字幕| 欧美刺激性大交免费视频| 亚洲日本中文字幕免费在线不卡| 日韩精品免费视频| 欧美日韩免费区域视频在线观看| 国产精品视频最多的网站| www高清在线视频日韩欧美| 亲爱的老师9免费观看全集电视剧| 在线视频中文亚洲| 亚洲aa中文字幕| 亚洲午夜久久久影院| 久久免费福利视频| 国产欧美精品一区二区| 日韩一区二区在线视频| 丝袜亚洲另类欧美重口| 欧美xxxx18国产| 欧美成人精品在线视频| 亚洲欧美国产精品va在线观看| 国产午夜精品美女视频明星a级| 久热精品视频在线| 91精品久久久久久久久久另类| 蜜臀久久99精品久久久无需会员| 久久成人亚洲精品| 欧美老少做受xxxx高潮| 欧美激情在线播放| 国产成人在线一区二区| 91av在线看| 亚洲天堂av在线免费观看| 日韩电影中文字幕av| 日韩成人av在线播放| 国产精品99蜜臀久久不卡二区| 亚洲精品一二区| 午夜精品久久久久久久99热| 亚洲精品美女免费| 亚洲精品乱码久久久久久按摩观| 久久精品99国产精品酒店日本| 久久久久久一区二区三区| 国产精品扒开腿爽爽爽视频| 色综合天天综合网国产成人网| 国产精品一区二区三区久久久| 欧美黑人巨大精品一区二区| 亚洲欧美日韩精品| 精品中文字幕久久久久久| 国产精品久久久久久久久久久久| 欧美激情xxxx| 欧美高清自拍一区| 成人一区二区电影| 国产中文字幕日韩| 欧美激情在线有限公司| 神马久久久久久| 久久99久久99精品免观看粉嫩| 8x拔播拔播x8国产精品| 中文字幕一区日韩电影| 欧美精品videofree1080p| 久久亚洲精品小早川怜子66| 亚洲国产小视频在线观看| 日韩毛片中文字幕| 亚洲精品资源美女情侣酒店| 欧美一级片一区| 国产成人精品最新| 狠狠久久五月精品中文字幕| 日韩高清免费在线| 亚洲成人黄色网| 欧美视频不卡中文| 精品久久久久久久久久ntr影视| 欧美午夜丰满在线18影院| 国产一区二区三区在线看| 国产精品9999| 欧美理论电影在线观看| 日韩在线中文视频| 成人黄色av免费在线观看| 国产xxx69麻豆国语对白| 久久久久久久国产精品视频| 庆余年2免费日韩剧观看大牛| 色综久久综合桃花网| 亚洲色图五月天| 欧美精品在线看| www.xxxx精品| 日韩电影大片中文字幕| 亚洲福利视频久久| 欧美日韩国产综合视频在线观看中文| 欧美另类第一页| 欧美激情综合色| 在线视频欧美日韩精品| 亚洲xxxx妇黄裸体| 国产一区二区丝袜高跟鞋图片| 国产亚洲精品综合一区91| 亚洲第一中文字幕在线观看| 中文字幕精品影院| 久久精品91久久久久久再现| 国模视频一区二区三区| 欧美性xxxxx极品娇小| 亚洲福利在线看| 中文字幕日韩高清| 91精品综合视频| 精品久久久久久国产| 成人福利视频网| 岛国av一区二区在线在线观看| 欧美精品www| 欧美激情亚洲视频| 亚洲日本成人网| 国产伦精品免费视频| 亚洲视频在线观看网站| 国产精品一区久久| 国产精品88a∨| 欧美极品在线视频| 一本大道香蕉久在线播放29| 亚洲美女自拍视频| 日韩高清a**址| 浅井舞香一区二区| 日韩精品视频在线观看网址| 亚洲国产一区二区三区在线观看| 欧美在线视频a| 日韩精品中文字幕视频在线| 欧美极品在线播放| 亚洲国产一区自拍| 久久久之久亚州精品露出| 一区二区三区视频观看| 日韩一区二区三区xxxx| 欧美久久久精品| 97国产一区二区精品久久呦| 亚洲精选一区二区| 亚洲欧美精品一区二区| 久久综合免费视频影院| 国产亚洲欧洲在线| 26uuu日韩精品一区二区| 欧美人交a欧美精品| 国产成人精品免费久久久久| 久久亚洲精品国产亚洲老地址| 亚洲欧美精品伊人久久| 成人国产精品日本在线| 国产精品欧美一区二区三区奶水| 欧美成人合集magnet| 国产精品视频精品视频| 亚洲免费视频在线观看| 欧美在线视频在线播放完整版免费观看| 国产女人18毛片水18精品| 91精品国产综合久久香蕉的用户体验| 日韩欧美综合在线视频| 日本免费一区二区三区视频观看| 伦理中文字幕亚洲| 国产成人一区二| 久久久天堂国产精品女人| 亚洲成人激情图| 精品久久久久久久久久久久久| 国产美女精品免费电影| 国产精品嫩草影院久久久| 欧美成年人视频网站欧美| 国产综合视频在线观看| 黑人精品xxx一区| 91夜夜未满十八勿入爽爽影院| 久久精品国产一区二区三区| 国产日韩综合一区二区性色av| 欧美专区福利在线| 欧美日韩午夜激情| 精品中文字幕久久久久久| 久久久久这里只有精品| 欧美午夜视频在线观看| 欧美黑人巨大xxx极品| 亚洲欧美福利视频| 精品福利在线看| 久久人人爽人人爽人人片av高请|