C / C++ 以Dijkstra为基础求最短路径及行进路线 伪代码及源代码

核心算法思路: 

        在迪杰斯特拉算法每次确定路径后优化路径时,当更新distance(记录最短路径长度的数组)值时也将信息写入散列,最后散列记录下来的路径即是最短路径的行进路线。

核心算法伪代码:

const int INF=100000 ;
void Widget::dijkstra(初始点)
{
    将path[]初始化为-1 		 //path是路径散列
    将vis[]初始化为0        //vis[i]为0表示节点i未被访问
    将distan[]初始化为INF	//distan[i]是i点到初始点的距离
    
	distan[begin]=0;		//将起始点到自身的距离设为0
    for(int i=0 ,开始遍历,遍历节点次)
    {
        int u = -1 , MIN = INF;//初始化u和MIN,u用于记录查找到MIN的位置(节点序号)
        for(int j=0 ,开始遍历,遍历节点次)
        {
            if(节点j未被访问 && distan[j]储存的值小于MIN)
            {
                记录该位置并更新MIN
            }
        }

        if(未找到新的MIN值,可说明剩余点不连通,退出算法)return ;
        vis[u] = true;		//记u被访问
        for(int v=0 ,开始遍历,遍历节点次)//开始对路径进行优化
        {
            if( v点未被访问 && 图上u和v连通 && distan[u]+d[u][v]<distan[v])//最后一个判断条件的意思是如果我从新添加的节点走向v比distan[v]记录的更短,说明前者更优
            {
                更新distan[v]为distan[u]+d[u][v]
                path[v]=u;//将v的上一路径点设置为u
            }
        }
    }

    return ;

}

核心算法C / C++源代码:

int dijkstra(int begin)
{
    for(int i=0;i<n;i++)
    {
        path[i]=-1;
        vis[i]=0;
        distances[i]=INF;
    }

    //起始点到其自身的距离设为0
    distances[begin]=0;

    for(int i=0;i<n;i++)
    {
        int u=-1,MIN=INF;
        for(int j=0;j<n;j++)
        {
            //从V-S中选择节点(V指全集,S指已经连通的节点)
            if( !vis[j] && distances[j]<MIN )
            {
                u=j;
                MIN=distances[j];
            }
        }
        //没有找到新的MIN值
        if(u==-1)
        {
            return 0;//非连通图
        }
        //记录u点已访问

        vis[u]=1;
        //优化路径
        for(int v=0;v<n;v++)
        {
            if(!vis[v] && distances[u]+d[u][v]<distances[v] )
            {
                distances[v]=distances[u]+d[u][v];
                //记录路径
                path[v]=u;
            }
        }
    }
    return 1;
}

 完整代码解释:

        下面的代码段是完整代码,包括核心函数,路径输出函数,测试数据(5*5矩阵,标签为从0到4); 不想再手搓一个栈用C++写的,栈的作用是将path的数据拿出来(由于path记录的是最短路径走到某一结点时该路径上的上一节点,所以是逆序的,用栈将其正序排列),测试时,输入的内容是起始点和终点,中间空格或回车隔开。

完整代码中测试用的邻接矩阵:

label:
0 1 2 3 4

Graph:
0 1 2 1 1
1 0 4 7 4
2 4 0 2 8
1 7 2 0 6
1 4 8 6 0

完整代码:

#include <iostream>
#include <stack>

using namespace std;

const int INF = 100000;//极大数

const int n=5;
int d[n][n];
int distances[n];
int path[n],vis[n];

void init();
int dijkstra(int begin);
void out_route(int end);

//path为散列,用于存放行进路线——上一个行进节点,vis用于标记某个节点是否被访问
int main()
{
    int b,e;
    scanf("%d%d",&b,&e);
    init();
    dijkstra(b);

    printf("min distance = %d\n",distances[e]);
    out_route(e);
    return 0;
}
void init()
{
    for(int i=0;i<n;i++)
    d[i][i]=0;

    d[0][1]=1; d[1][0]=1;
    d[0][2]=2; d[2][0]=2;
    d[0][3]=1; d[3][0]=1;
    d[0][4]=1; d[4][0]=1;

    d[1][2]=4; d[2][1]=4;
    d[1][3]=7; d[3][1]=4;
    d[1][4]=4; d[4][1]=7;

    d[2][3]=2; d[3][2]=2;
    d[2][4]=8; d[4][2]=8;

    d[3][4]=6; d[4][3]=6;
}
/**
label:
0 1 2 3 4

Graph:
0 1 2 1 1
1 0 4 7 4
2 4 0 2 8
1 7 2 0 6
1 4 8 6 0
*/

//默认邻接矩阵为5*5
int dijkstra(int begin)
{
    for(int i=0;i<n;i++)
    {
        path[i]=-1;
        vis[i]=0;
        distances[i]=INF;
    }

    //起始点到其自身的距离设为0
    distances[begin]=0;

    for(int i=0;i<n;i++)
    {
        int u=-1,MIN=INF;
        for(int j=0;j<n;j++)
        {
            //从V-S中选择节点(V指全集,S指已经连通的节点)
            if( !vis[j] && distances[j]<MIN )
            {
                u=j;
                MIN=distances[j];
            }
        }
        //没有找到新的MIN值
        if(u==-1)
        {
            return 0;//非连通图
        }
        //记录u点已访问

        vis[u]=1;
        //优化路径
        for(int v=0;v<n;v++)
        {
            if(!vis[v] && distances[u]+d[u][v]<distances[v] )
            {
                distances[v]=distances[u]+d[u][v];
                //记录路径
                path[v]=u;
            }
        }
    }
    return 1;
}
//连通时使用,用于显示路径
void out_route(int end)
{
    stack<int> st;
    st.push(end);
    while(path[end]!=-1)
    {
        st.push(path[end]);
        end=path[end];
    }
    printf("min route : ");
    while(!st.empty())
    {
        printf("%d ",st.top());
        st.pop();
    }
}

运行结果:

 

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值