分治界限法(优先队列优化)求解单源最短路径,并输出源点到其他点的最近的路径

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <fstream>
#include <iostream>
#include <istream>
#include <iterator>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <utility>
#include <vector>

#include "MinHeap.h"
#define MAX 0xfffff
using namespace std;
unsigned n, m;//假设最多10个顶点
vector<vector<int>> e = {
        vector<int>(11),
        vector<int>(11),
        vector<int>(11),
        vector<int>(11),
        vector<int>(11),
        vector<int>(11),
        vector<int>(11),
        vector<int>(11),
        vector<int>(11),
        vector<int>(11),
        vector<int>(11),
};//邻接矩阵
vector<Node>  dis(10);//源点1到其他所有点的最短距离
vector<PreNode> pre(10);//前趋节点
vector<bool> book(10);//标志数组,区别dis的P,Q集合
/*
 CLion 使用提示 :

  批量注释代码 => Ctrl + shift + /
  格式化代码   => option + command + L
  补全语句     => Shift + command + return
  生成构造器,getter和setter方法等 => control + return
  行注释       => control + /
  块注释       => control + shift + c
*/
/*
 * 输出顶点i的最短路径
 */
void printSolution(unsigned index){
    stack<int> s;
    int i=n;
    if (2<=index&&index<=n) {
        while (index!=0){
            s.push(index);
            index=pre[index].preIndex;
        }
    }
    printf("路径{");
    while (!s.empty()){
        printf("%u " , s.top());
        s.pop();
    }
    printf("}\n");
}
void print(){
    for (int i = 2; i <= n; ++i) {
        printSolution(i);
    }
}
void solution() {
    int T,p1,p2,cost;
    printf("请输入一个数T,代表运行算法T次\n");
    scanf("%d", &T);
    while (T--) {
        printf("请输入顶点个数和边数\n");
        scanf("%d %d", &n, &m);
        /*
         *
         */
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= n; ++j) {
                e[i][j] = e[j][i] = (i == j ? 0 : MAX);//自己到自己是0花费,否则先假设为∞距离
            }
        }
        /*
         * 读入边权值,假设无向图,则e[p1][p2]都有相同都耗费
         */
        for (int i = 1; i <= m; ++i) {
            printf("请输入第%d条边(A,B,cost)路程耗费\n",i);
            scanf("%d %d %d" , &p1 ,&p2 , &cost);
            e[p1][p2]=e[p2][p1]=cost;//无向图
        }
        dis[1].cost=0;
        dis[1].curNode=1;
        pre[1].curNode=1;
        pre[1].preIndex=0;//很重要,防止死循环!!
        for (int i = 2; i <= n; ++i) {
            dis[i].cost=e[1][i];
            dis[i].curNode=i;//v1对应1号点,v2对应2号点,v3对应3号点
            if (dis[i].cost!=MAX) {
                pre[i].preIndex=1;//开始的时候假设都是1到其余各点,所以如果有边的关系,则前趋节点就是1
                pre[i].curNode=i;//v1则是1,v2则是2
            } else{
                pre[i].preIndex=-1;//无边则设置为-1
                pre[i].curNode=i;//v1则是1,v2则是2
            }
            book[i]= false;
        }
        book[1]=true;
        MinHeap heap(dis,n);//构造最小堆
        while (!heap.empty()){
            Node min_cost = heap.top();//每次取出最小的cost的顶点
            for (int i = 2; i <= n; ++i) {
                if (e[min_cost.curNode][i]<MAX&&
                    ((dis[min_cost.curNode].cost+e[min_cost.curNode][i])<dis[i].cost)) {
                    pre[i].preIndex=min_cost.curNode;
                    dis[i].cost=dis[min_cost.curNode].cost+e[min_cost.curNode][i];
                }
            }
            heap.pop();
        }
        print();
    }
}

int main() {
    solution();
    return 0;
}
/*
 1
 5 6
 1 2 7
 1 3 14
 2 4 2
 3 4 3
 3 5 4
 4 5 1

 */

头文件在下面这里:👇

//
// Created by 何维刚 on 2021-04-25.
//
#pragma once
#ifndef DIJIESITELA_MINHEAP_H
#define DIJIESITELA_MINHEAP_H

#include <vector>

using namespace std;
struct PreNode{
    unsigned curNode;//节点v1则是1,v2则是2
    int preIndex;//该节点的前趋节点
    PreNode(unsigned _curNode=0, int _preIndex=-1):curNode(_curNode),preIndex(_preIndex){}
};
struct Node {
    unsigned curNode;
    unsigned cost;

    Node(unsigned _curNode = 0, unsigned _cost = 0) : curNode(_curNode), cost(_cost) {}

    Node &operator=(const Node &N) {
        if (&N == this) {
            return *this;
        }
        this->curNode = N.curNode;
        this->cost = N.cost;
        return *this;
    }

    friend ostream &operator<<(ostream &os, const Node &N) {
        printf("(curNode:%u,cost:%u)\n", N.curNode, N.cost);
        return os;
    }
};

class MinHeap {
public:
    vector<Node> v;
    unsigned curSize, n;

    MinHeap(const vector<Node> &vv,int n);

    Node &top();

    void pop();

    void push(const Node &x);

    void percolateDown(int i);

    bool empty() const;

    void buildHeap();

    Node &deleteMin();
};

MinHeap::MinHeap(const vector<Node> &vv,int n) : v(n), curSize(n-1) {
    for (int i = 0; i <= n-2; ++i) {
        v[i + 1] = vv[i+2];
    }
    buildHeap();
}

Node &MinHeap::top() {
    return v[1];
}

void MinHeap::pop() {
    if (empty()) {
        printf("Error in pop empty heap!!\n");
        return;
    }
    v[1] = v[curSize--];
    percolateDown(1);
}

void MinHeap::push(const Node &x) {
    if (curSize == v.size() - 1) {
        v.resize(v.size() * 2);
    }
    int hole = ++curSize;
    for (; hole > 1 && x.cost < v[hole / 2].cost; hole /= 2)
        v[hole] = v[hole / 2];
    v[hole] = x;
}

void MinHeap::percolateDown(int hole) {
    int child;
    Node tmp = v[hole];
    for (; hole * 2 <= curSize; hole = child) {
        child = hole * 2;
        if (child != curSize && v[child + 1].cost < v[child].cost) {
            child++;
        }
        if (v[child].cost < tmp.cost) {
            v[hole] = v[child];
        } else {
            break;
        }
    }
    v[hole] = tmp;
}

bool MinHeap::empty() const {
    return curSize == 0;
}

void MinHeap::buildHeap() {
    for (int i = curSize / 2; i >= 1; --i) {
        percolateDown(i);
    }
}

#endif //DIJIESITELA_MINHEAP_H

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿维的博客日记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值