图的最短路径dijkstra算法

想法是这样的:

1. 最开始要建立4个list,分别存储

    a. 所有的Vertex: allVertex[]

    b. 一个空的Vertex list: emptyVertex[]

    c. 一个前缀表 previous list(用来回溯路径用): previous[]

    d. 一个表示最短距离的表(就是表示某个点与0点的最短距离):

前两个list是用来辅助操作的,后2个表则是输出,通过后2个表我们能得到想要的一切结果。

因此我们的任务其实就是,最终把c。d两个表填充完毕即可。

2. 我们要做一个循环,循环次数为VertexMax次,因为如果是连通图,每次循环都能处理一个Vertex。

3. 第一次循环前我们把start这个vertex从allVertex表,移动到emptyVertex表。

4. 这样我们就需要遍历,与empty表所有vertex关联的每一条line。找出这些line中最短的一条。

5. 找到最短的这条line之后,更新一下previous表,previous[line->end] = start; 然后更新一下distances表, (distances[line->end]) 同 (distances[start] + line->weight)取最小值

6. 然后,line->end作为新的start,重新进入循环。。重复3-5步即可。

#include <iostream>
using namespace std;

const int MAX_VERTEX = 5;//图的顶点数
const int MAX_INT = 0x7fffffff;//4字节的整数
const int MIN_INT = 0xffffffff;//4字节的整数
enum Kind{NG, DG};//无向图,有向图
Kind k = NG;//图的种类
int graph[MAX_VERTEX][MAX_VERTEX];//图
int emptyVertex[MAX_VERTEX];//空的Vertex集合
int allVertex[MAX_VERTEX];//当前Vertex集合
int previous[MAX_VERTEX];//前缀
int distances[MAX_VERTEX];//distance

void printGraph(){//打印图
    cout<<"-----------begin-------------"<<endl;
    for(int i = 0; i < MAX_VERTEX; i++){
        for(int j = 0; j < MAX_VERTEX; j++){
            if(graph[i][j] < MAX_INT){
                cout<<graph[i][j]<<"\t";
            }else{
                cout<<"∞\t";
            }
        }
        cout<<"\n\v";
    }
    cout<<"-----------end-------------"<<endl;
}

void printArr(int *arr, int len){//打印数组
    for(int i = 0; i < len; i++){
        if(arr[i] >= MAX_INT){
            cout<<"∞\t";
        }else{
            cout<<arr[i]<<"\t";
        }
    }
    cout<<endl;
}

void printSituation(){//打印整个结构的各个数据部分。
    cout<<"[[======================================"<<endl;
    //cout<<"graph:\n";
    //printGraph();
    cout<<"allVertex:\n";
    printArr(allVertex, MAX_VERTEX);
    cout<<"emptyVertex:\n";
    printArr(emptyVertex, MAX_VERTEX);
    cout<<"previous:\n";
    printArr(previous, MAX_VERTEX);
    cout<<"distances:\n";
    printArr(distances, MAX_VERTEX);
    cout<<"======================================]]"<<endl;
}

void init(){//初始化
    for(int i = 0; i < MAX_VERTEX; i++){
        emptyVertex[i] = MAX_INT;
        allVertex[i] = i;
        previous[i] = MAX_INT;
        distances[i] = MAX_INT;
        for(int j = 0; j < MAX_VERTEX; j++){
            graph[i][j] = MAX_INT;
        }
    }
    distances[0] = 0;
}

void addLine(int start, int end, int weight){//增加一条line
    if(start >= MAX_VERTEX || end >= MAX_VERTEX) return;
    graph[start][end] = weight;
    if(k == NG){
        graph[end][start] = weight;
    }
}

void rmLine(int start, int end){//移除一条line
    if(start >= MAX_VERTEX || end >= MAX_VERTEX) return;
    graph[start][end] = MAX_INT;
    if(k == NG){
        graph[end][start] = MAX_INT;
    }
}

void dijkstra(){
    int start = 0;
    int emptyI = 0;//emptyVertex数组的下标
    int numHandled = 0;//每次循环都能处理一个vertex,因此需要循环MAX_VERTEX次。
    while(numHandled < MAX_VERTEX){
        //1. 把start从allVertex中取出,放入emptyVertex中
        emptyVertex[emptyI++] = allVertex[start];
        allVertex[start] = MAX_INT;
        //2. 找出 已经加入到 empty中的所有点上 的所有的line, 选出其中最短的一条,其end点作为下一次访问的起始点。
        //3. 根据这些line重新计算distances, 更新distances表--同时更新前缀表,前缀表是随着distances表变化的。
        int shortestWeight = MAX_INT;
        int shortestEnd = MIN_INT;
        for(int j = 0; j < MAX_VERTEX; j++){
            int currentStart = emptyVertex[j];
            if(currentStart < MAX_INT){//每一个在empty中的vertex都必须参加比较。在所有的这些vertex中关联的line中选一条 end 值不在empty中的最短的line。
                for(int i = 0; i < MAX_VERTEX; i++){//i值表示 (currentStart -> i) 这条 line 的 end值
                    if(graph[currentStart][i] >= MAX_INT) {//如果这条line不存在,搜索下一条
                        continue;
                    }
                    else{
                        if(allVertex[i] != MAX_INT && shortestWeight > graph[currentStart][i]){//并且这条line不能是计算过的。如果合法,则比较当前最小的weight。
                            shortestWeight = graph[currentStart][i];//选中这条line。
                            shortestEnd = i;//记住这条line。
                            if(distances[i] >= MAX_INT){//调整distances和previous.
                                distances[i] = graph[currentStart][i] + distances[currentStart];
                                previous[i] = currentStart;
                            }else{
                                if(distances[currentStart] + graph[currentStart][i] < distances[i]){
                                    distances[i] = distances[currentStart] + graph[currentStart][i];
                                    previous[i] = currentStart;
                                }
                            }
                        }
                    }
                }
            }
        }
        //4. 把最短的line的end作为新的start重新循环,
        if(shortestEnd == MIN_INT){
            cout<<"error!! shortestEnd == MIN_INT"<<endl;
        }else{
            cout<<"&&shortest line "<<shortestEnd<<", shortestWeight = "<<shortestWeight<<endl;
            start = shortestEnd;
        }
        //5. numHandled++
        numHandled++;
        printSituation();
    }
}

int main(){
    init();
    /*addLine(0, 1, 5);
    addLine(1, 2, 7);
    addLine(1, 4, 5);
    addLine(2, 3, 8);
    addLine(2, 4, 9);
    addLine(2, 5, 7);
    
    addLine(3, 5, 5);
    addLine(4, 5, 15);
    addLine(4, 6, 6);
    
    addLine(5, 6, 8);
    addLine(5, 7, 9);
    addLine(6, 7, 11);*/
    k = DG;
    addLine(0, 1, 10);
    addLine(0, 3, 30);
    addLine(0, 4, 100);
    addLine(1, 2, 50);
    addLine(2, 4, 10);
    addLine(3, 2, 20);
    addLine(3, 4, 60);
    dijkstra();
}

。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
动态规划是一种解决复杂问题的数学方法,通过将问题划分为多个子问题,并将子问题的解保存起来,以便后续使用。最短路径Dijkstra算法是一种基于贪心策略的算法,用于计算一个中一个节点到其他所有节点的最短路径。该算法通过不断更新已知的最短路径来逐步确定最短路径的值。在每一步中,Dijkstra算法会选择当前最短路径距离最小的节点,并更新与该节点相邻的节点的距离值。这样,经过多轮迭代后,最终得到了一个节点到其他所有节点的最短路径。<span class="em">1</span><span class="em">2</span> #### 引用[.reference_title] - *1* [最短路径 Dijkstra算法C语言实现](https://download.csdn.net/download/zhilanyushu/10116827)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [基于多最短路径Dijkstra算法和动态规划的导航系统](https://download.csdn.net/download/qq_63761366/87315059)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值