单源最短路径的迪克斯特拉(Dijkstra)算法的改进

Dijkstra算法

1.定义概览

Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点(节点需为源点)到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。Dijkstra算法是很有代表性的最短路径算法,注意该算法要求图中不存在负权边。

 实例:假设有A,B,C,D四个城市,(这里讨论的是有向网) 它们的距离为:  A->B(10),A->C(11),B->D(12),C->D(13);

所谓単源路径就是解决从源点 A开始找出到其他城市的最短距离(除本身外的其他所有城市)。Dijkstra算法可以求出A->B(10),A->C(11),A->D(22);

拓展2:多源最短路径(常用Floyd算法)是解决任意两点间的最短路径的一种算法,(不局限于从源点出发,到其他各个顶点 )可以正确处理有向图或负权的最短路径问题,同时也被用于计算有向图的传递闭包。Floyd算法的时间复杂度为O(N3),空间复杂度为O(N2)。

图的创建:

void createGraph(tnode t){
    cout<<"输入顶点和边数:"<<endl;
    cin>>t->v>>t->e;
    cout<<"输入顶点信息:"<<endl;
    for(int i = 1;i<=t->v;i++){
         cin>>t->vex[i];
    }
    for(int i = 1;i<=t->v;i++){
        for(int j = 1;j<=t->v;j++){
           t->wei[i][j] = LIMITLESS;
        }
    }
    cout<<"输入两连接点下标和权值:"<<endl;
    int k1,k2,weight;
    for(int i = 1;i<=t->e;i++){
        cin>>k1>>k2>>weight;
        t->wei[k1][k2] = weight;
    }
}
void  printGraph(tnode t){
       for(int i = 1;i<=t->v;i++){
          for(int j = 1;j<=t->v;j++){
              if(t->wei[i][j]!=LIMITLESS){
                  cout<<t->wei[i][j]<<"  ";
              }
              else{
                  cout<<"oo"<<"  ";
              }
          }
          cout<<endl;
      }
}

dijkstra算法:

void dijkstra(tnode t,int sour){
     bool s[MAX_NUM];              //标识
     int dist[MAX_NUM];           //源点到顶点距离
     int prev[MAX_NUM] = {0};    //顶点的前置顶点
     for(int i = 1;i<=t->v;i++){
        dist[i] = t->wei[sour][i]; //记录从源点到各顶点的路径长
        s[i] = false;              //初始化标识数组
        if(dist[i]!=LIMITLESS){    //若源点到顶点的距离不为空,则将源点置为顶点的前置点
           prev[i] = sour;
        }
        else{
            prev[i] = 0;         //0表示前置节点不存在
        }
     }
     dist[sour] = 0,s[sour] = true;
     for(int i = 1;i<t->v;i++){
         int item = LIMITLESS;
         int flag = sour;
         for(int j = 1;j<=t->v;j++){      //找到距源点距离最小且未被标识过的顶点
             if(!s[j]&&dist[j]<item){
                 flag = j;
                 item = dist[j];
             }
         }
         s[flag] = true;
         for(int i = 1;i<=t->v;i++){         //从上面找到的顶点向其它顶点探索,优化源点到其他顶点的距离
             if(!s[i]&&t->wei[flag][i]<LIMITLESS){
                int newdist = dist[flag]+t->wei[flag][i];
                if(newdist<dist[i]){        //其它顶点距离更新
                    dist[i] = newdist;
                    prev[i] = flag;
                }
             }
         }
     }
     stack<int> ss[MAX_NUM];        //栈实现打印路径构建
     for(int i = 1;i<=t->v;i++){
         cout<<"\n源点到顶点"<<i<<"的最短距离为:"<<dist[i];
         cout<<",最短路径构建为:"<<endl;
         int p = prev[i];
         if(!p){
             cout<<"源点到自身路径构建为空!"<<endl;
         }else{
             while(p){
                ss[i].push(p);
                p = prev[p];
             }
             while(!ss[i].empty()){
                int k = ss[i].top();
                cout<<k;
                ss[i].pop();
                if(!ss[i].empty()){
                    cout<<"->";
                }
             }
             if(i!=sour) cout<<"->"<<i;     //顶点自身值打印
         }
     }

完整代码:

/**
   @单源最短路径(dijkstra算法)
*/
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<stack>
#define MAX_NUM 50
#define LIMITLESS 65535
using namespace std;
typedef struct Tnode{
    int v,e;
    int vex[MAX_NUM];
    int wei[MAX_NUM][MAX_NUM];
}Tnode,*tnode;
void createGraph(tnode t){
    cout<<"输入顶点和边数:"<<endl;
    cin>>t->v>>t->e;
    cout<<"输入顶点信息:"<<endl;
    for(int i = 1;i<=t->v;i++){
         cin>>t->vex[i];
    }
    for(int i = 1;i<=t->v;i++){
        for(int j = 1;j<=t->v;j++){
           t->wei[i][j] = LIMITLESS;
        }
    }
    cout<<"输入两连接点下标和权值:"<<endl;
    int k1,k2,weight;
    for(int i = 1;i<=t->e;i++){
        cin>>k1>>k2>>weight;
        t->wei[k1][k2] = weight;
    }
}
void  printGraph(tnode t){
       for(int i = 1;i<=t->v;i++){
          for(int j = 1;j<=t->v;j++){
              if(t->wei[i][j]!=LIMITLESS){
                  cout<<t->wei[i][j]<<"  ";
              }
              else{
                  cout<<"oo"<<"  ";
              }
          }
          cout<<endl;
      }
}
void dijkstra(tnode t,int sour){
     bool s[MAX_NUM];              //标识
     int dist[MAX_NUM];           //源点到顶点距离
     int prev[MAX_NUM] = {0};    //顶点的前置顶点
     for(int i = 1;i<=t->v;i++){
        dist[i] = t->wei[sour][i]; //记录从源点到各顶点的路径长
        s[i] = false;              //初始化标识数组
        if(dist[i]!=LIMITLESS){    //若源点到顶点的距离不为空,则将源点置为顶点的前置点
           prev[i] = sour;
        }
        else{
            prev[i] = 0;         //0表示前置节点不存在
        }
     }
     dist[sour] = 0,s[sour] = true;
     for(int i = 1;i<t->v;i++){
         int item = LIMITLESS;
         int flag = sour;
         for(int j = 1;j<=t->v;j++){      //找到距源点距离最小且未被标识过的顶点
             if(!s[j]&&dist[j]<item){
                 flag = j;
                 item = dist[j];
             }
         }
         s[flag] = true;
         for(int i = 1;i<=t->v;i++){         //从上面找到的顶点向其它顶点探索,优化源点到其他顶点的距离
             if(!s[i]&&t->wei[flag][i]<LIMITLESS){
                int newdist = dist[flag]+t->wei[flag][i];
                if(newdist<dist[i]){        //其它顶点距离更新
                    dist[i] = newdist;
                    prev[i] = flag;
                }
             }
         }
     }
     stack<int> ss[MAX_NUM];        //栈实现打印路径构建
     for(int i = 1;i<=t->v;i++){
         cout<<"\n源点到顶点"<<i<<"的最短距离为:"<<dist[i];
         cout<<",最短路径构建为:"<<endl;
         int p = prev[i];
         if(!p){
             cout<<"源点到自身路径构建为空!"<<endl;
         }else{
             while(p){
                ss[i].push(p);
                p = prev[p];
             }
             while(!ss[i].empty()){
                int k = ss[i].top();
                cout<<k;
                ss[i].pop();
                if(!ss[i].empty()){
                    cout<<"->";
                }
             }
             if(i!=sour) cout<<"->"<<i;     //顶点自身值打印
         }
     }
}
int main(){
     Tnode t;
     createGraph(&t);
     cout<<"构建的图为:"<<endl;
     printGraph(&t);
     cout<<"dijkstra算法构建的顶点最短路径为:"<<endl;
     dijkstra(&t,1);
    return 0;
}
/*
1 2 10
1 4 30
1 5 100
2 3 50
3 5 10
4 3 20
4 5 60
*/

《单源最短路径的迪克斯特拉(Dijkstra)算法的改进》

    原文作者:Dijkstra算法
    原文地址: https://blog.csdn.net/lfb637/article/details/80176172
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞