数据结构 笔记:最短路径(Floyd)

问题的提法

-已知一个各边权值均大于0的带权有向图,对每一对顶点Vi≠Vj,求出Vi与Vj之间的最短路径值以及最短路径上的顶点。

Floyd算法核心

n阶方阵中元素的意义

-A^-1[i][j]:Vi到Vj的权值,无中间顶点

-A^0[i][j]:Vi到Vj的路径长度,路径的中间顶点为0

-A^1[i][j]:Vi到Vj的路径长度,路径的中间顶点可能为0或1

-……

-A^k[i][j]:Vi到Vj的路径长度,路径的中间顶点编号不大于k

-……

-A^n-1[i][j]:Vi到Vj的最短路径长度

Floyd算法精髓

-A^-1定义为邻接矩阵,则:

·A^0,……,A^n-1通过中转顶点逐一递推得到

-A^k矩阵中元素的更新:

·A^k[i][j] = min{ A^k-1[i][j],A^k-1[i][k] + A^k-1[k][j] }

-A矩阵的推导就是最短路径的推导

·矩阵的推导就是最短路径的推导

·A[i][j]为i到j的路径值,在推导过程中逐步减小

Floyd算法的实现:初始化

-本质:使用邻接矩阵初始化A^-1

for(int i = 0;i<vCount() ;i++)
{
    for(int j = 0;j<vCount();j++)
    {
        dist[i][j] = getEdge(i,j);
    }
}

Floyd算法的实现: A^0,...,A^n-1矩阵推导

-本质:使用中转顶点逐步推导最短路径

for(int k = 0;k<vCount();k++)
{
    for(int i = 0;i<vCount();i++)
    {

        for(int j = 0;j<vCount() ;j++)
        {
            if(dist[i][k] + dist[k][j] < dist[i][j])
            {
                dist[i][j] = dist[i][k]  + dist[k][j];
            }
        }
    }
}

定义辅助矩阵:

-int path[N][N];   //路径矩阵

·path[i][j]表示i到j的路径上所经过的第一个顶点

·初始化:path[i][j] = -1; or path[i][j] = j;

·修改:

if((dist[i][k] + dist [k][j]) < dist[i][j])
{
    dist[i][j] = dist[i][k] + dist[k][j];
    path[i][j] = path[i][k];
}
SharedPointer<Array<int>> floyd(int x,int y ,const E& LIMIT)
    {
        LinkQueue<int> ret;

        if((0 <= x) && (x <= vCount()) && (0 <= y) && (y < vCount()))
        {
            DynamicArray<DynamicArray<E>> dist(vCount());
            DynamicArray<DynamicArray<int>> path(vCount());

            for(int k = 0;k<vCount();k++)
            {
                dist[k].resize(vCount());
                path[k].resize(vCount());
            }

            for(int i = 0;i<vCount();i++)
            {
                for(int j = 0;j<vCount();j++)
                {
                    path[i][j] = -1;
                    dist[i][j] = isAdjacent(i,j)?getEdge(i,j) : LIMIT;
                }
            }

            for(int k = 0;k < vCount(); k++)
            {
                for(int i = 0;i < vCount();i++)
                {
                    for(int j =0;j<vCount();j++)
                    {
                        if((dist[i][k] + dist[k][j]) < dist[i][j])
                        {
                            path[i][j] = -1;
                            dist[i][j] = isAdjacent(i,j) ? (path[i][j] = j,getEdge(i,j)) : LIMIT;
                        }
                    }
                }
            }

            for(int k = 0;k<vCount();k++)
            {
                for(int i = 0;i<vCount();i++)
                {

                    for(int j = 0;j<vCount() ;j++)
                    {
                        if(dist[i][k] + dist[k][j] < dist[i][j])
                        {
                            dist[i][j] = dist[i][k]  + dist[k][j];
                            path[i][j] = path[i][k];
                        }
                    }
                }
            }

            while((x != -1) && ( x != y))
            {
                ret.add(x);
                x = path[x][y];
            }

            if(x != -1)
            {
                ret.add(x);
            }
        }
        else
        {
            //抛出异常
        }

        if(ret.length() < 2)
        {
            //抛出异常
        }

        return toArray(ret);
    }

总结:

-Floyd算法通过递推逐步求得所有顶点间的最短路径

-Floyd算法的本质是通过中转顶点寻找更短的路径

-邻接矩阵是最短路径推导的其实矩阵

-路径矩阵记录了最短路径上的各个顶点

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值