C++——迪杰斯特拉算法&弗洛伊德算法(Dijkstra&Floyd)for Neuedu

29 篇文章 1 订阅
18 篇文章 0 订阅

采用迪杰斯特拉算法和弗洛伊德算法

求出两个景点间的最短路径和最短距离

  • 例如下图所示的无向图:
    通过输入节点个数和线路条数,分别输入各线路权值进行计算最短(最优)线路。
  • Ps:使用Qt进行编译运行

在这里插入图片描述

/*
 * 基于最短路径的景点规划
 * 简介:分别采用迪杰斯特拉算法和弗洛伊德算法,求出两个景点间的最短路径和最短距离。
 * 作者:181203616-宋明桥-GodOuO
 * 修改履历:
 *  21年4月,创建文件
*/

#include<iostream>
#include<string>
using namespace std;

class Dis {
public:
    Dis() {
        visit = false;
        value = 0;
        path = "";
    }
public:
string path;
    int value;
    bool visit;
};
class Graph_fld {
public:
    Graph_fld(int vexnum, int edge);
    ~Graph_fld();
    bool check_edge_value(int start, int end, int weight);
    void createGraph(int);
    void Floyd();
    void print_path(int);
    void print();
private:
    int vexnum;
    int edge;
    int **arc;
    int ** dis;
    int ** path;
};
class Graph_dis {
public:
    Graph_dis(int vexnum, int edge);
    ~Graph_dis();
    bool check_edge_value(int start, int end, int weight);
    void createGraph();
    void print();
    void Dijkstra(int begin);
    void print_path(int);
private:
    int vexnum;   //图的顶点个数
    int edge;     //图的边数
    int **arc;   //邻接矩阵
    Dis * dis;   //记录各个顶点最短路径的信息
};

Graph_fld::Graph_fld(int vexnum, int edge) {
    this->vexnum = vexnum;
    this->edge = edge;
    arc = new int*[this->vexnum];
    dis = new int*[this->vexnum];
    path = new int*[this->vexnum];
    for (int i = 0; i < this->vexnum; i++) {
        arc[i] = new int[this->vexnum];
        dis[i] = new int[this->vexnum];
        path[i] = new int[this->vexnum];
        for (int k = 0; k < this->vexnum; k++) {
            arc[i][k] = INT_MAX;
        }}}
Graph_dis::Graph_dis(int vexnum, int edge) {//初始化顶点数和边数
    this->vexnum = vexnum;
this->edge = edge;
arc = new int*[this->vexnum];
    dis = new Dis[this->vexnum];
    for (int i = 0; i < this->vexnum; i++) {
        arc[i] = new int[this->vexnum];
        for (int k = 0; k < this->vexnum; k++) {
                arc[i][k] = INT_MAX;
        }}}

Graph_fld::~Graph_fld() {
    for (int i = 0; i < this->vexnum; i++) {
        delete this->arc[i];
        delete this->dis[i];
        delete this->path[i];
    }
    delete dis;
    delete arc;
    delete path;
}
Graph_dis::~Graph_dis() {
    delete[] dis;
    for (int i = 0; i < this->vexnum; i++) {
        delete this->arc[i];
    }
    delete arc;
}

bool Graph_fld::check_edge_value(int start, int end, int weight) {
    if (start<1 || end<1 || start>vexnum || end>vexnum || weight < 0) {
        return false;
    }
    return true;
}
bool Graph_dis::check_edge_value(int start, int end, int weight) {
    if (start<1 || end<1 || start>vexnum || end>vexnum || weight < 0) {
        return false;
    }
    return true;
}


void Graph_fld::createGraph(int kind) {
    cout << "请输入每条边的起点和终点(顶点编号从1开始)以及其权重:('1 2 8'-“V1到V2距离为8”)" << endl;
    int start;
    int end;
    int weight;
    int count = 0;
    while (count != this->edge) {
        cin>>start>>end>>weight;
        while (!this->check_edge_value(start,end,weight)) {
            cout<<"输入的边的信息不合法,请重新输入"<<endl;
            cin>>start>>end>>weight;
        }
        arc[start - 1][end - 1] = weight;
        if(2==kind)
            arc[end-1][start-1] = weight;
        ++count;}}
void Graph_dis::createGraph() {
    cout << "请输入每条边的起点和终点(顶点编号从1开始)以及其权重" << endl;
    int start;
    int end;
    int weight;
    int count = 0;
    while (count != this->edge) {
        cin >> start >> end >> weight;
                while (!this->check_edge_value(start, end, weight)) {
            cout << "输入的边的信息不合法,请重新输入" << endl;
            cin >> start >> end >> weight;
        }
    arc[start - 1][end - 1] = weight;
        arc[end - 1][start - 1] = weight;
        ++count;
    }}

void Graph_fld::Floyd() {
    int i=0,j=0;
    for (i= 0; i< this->vexnum; i++) {
        for (j=0; j< this->vexnum; j++) {
            this->dis[i][j] = this->arc[i][j];
            this->path[i][j] = j;}}
    int n=0;
    for (int m = 0;m<this->vexnum;m++) {
        for (i = 0;i < this->vexnum; i++) {
            for (j = 0; j< this->vexnum; j++) {
                n=(dis[i][m]==INT_MAX||dis[m][j] == INT_MAX)?INT_MAX:(dis[i][m] + dis[m][j]);
                if (this->dis[i][j]>n) {
                    this->dis[i][j]=n;
                    this->path[i][j]=this->path[i][m];
                }}}}}
void Graph_dis::Dijkstra(int begin){
    int i;
    for (i = 0; i < this->vexnum; i++) {
        dis[i].path = "v" + to_string(static_cast<long long>(begin)) + "-->v" + to_string(static_cast<long long>(i + 1));
        dis[i].value = arc[begin - 1][i];
    }
    dis[begin - 1].value = 0;
    dis[begin - 1].visit = true;
    int count = 1;
    while (count != this->vexnum) {
        int temp=0;
        int min = INT_MAX;
        for (i = 0; i < this->vexnum; i++) {
            if (!dis[i].visit && dis[i].value<min) {
                min = dis[i].value;
                temp = i;
            }}
        dis[temp].visit = true;
        ++count;
        for (i = 0; i < this->vexnum; i++) {
            if (!dis[i].visit && arc[temp][i]!=INT_MAX && (dis[temp].value + arc[temp][i]) < dis[i].value) {
                dis[i].value = dis[temp].value + arc[temp][i];
                dis[i].path = dis[temp].path + "-->v" + to_string(static_cast<long long>(i + 1));
            }}}}

void Graph_fld::print() {
    cout << "图的邻接矩阵为:" << endl;
    int i = 0; //i代表打印行
    int j = 0; //j代表打印列
    while (i != this->vexnum) {
        j = 0;
        while (j!= this->vexnum) {
            if (arc[i][j] == INT_MAX)
                cout << "∞" << " ";
            else
                cout << arc[i][j] << " ";
            ++j;
        }
        cout << endl;
        ++i;
    }}
void Graph_dis::print() {
    cout << "图的邻接矩阵为:" << endl;
    int i= 0; //打印行
    int j= 0; //打印列
    while (i != this->vexnum) {
        j= 0;
        while (j!= this->vexnum) {
            if (arc[i][j] == INT_MAX)
                cout << "∞" << " ";
            else
            cout << arc[i][j] << " ";
            ++j;}
        cout << endl;
        ++i;
    }}

void Graph_fld::print_path(int begin) {
    cout << "各个顶点对的最短路径:" << endl;
    int i = 0;
    int j = 0;
    int m = 0;
    for (i=begin-1;i<begin;i++) {
        for (j= 0; j< this->vexnum;j++) {
            if(0!=(to_string(static_cast<long long>(i+ 1)).compare(to_string(static_cast<long long>(j+ 1))))){
                cout << "v" << to_string(static_cast<long long>(i+ 1)) << "---" << "v" << to_string(static_cast<long long>(j+ 1)) << "最短路径长度为: "
                     << this->dis[i][j] << "\n\t\t\t最短路径为: " << "v" << to_string(static_cast<long long>(i+ 1));
                m = path[i][j];
                while (m!= j) {
                    cout << "-->" << "v" << to_string(static_cast<long long>(m + 1));
                    m= path[m][j];
                }
                cout << "-->" << "v" << to_string(static_cast<long long>(j + 1));

                cout << endl;}
            else{cout << "v" << to_string(static_cast<long long>(i+ 1)) << "---" << "v" << to_string(static_cast<long long>(j+ 1)) << "最短路径长度为: "
                      <<0 << "\n\t\t\t最短路径为: v" << to_string(static_cast<long long>(i+ 1)) << "-->v"<<to_string(static_cast<long long>(j+ 1))<<endl;}
        }}}
void Graph_dis::print_path(int begin) {
    string str;
    str = "v" + to_string(static_cast<long long>(begin));
    cout << "以"<<str<<"为起点的图的最短路径为:" << endl;
    for (int i = 0; i != this->vexnum; i++) {
        if(dis[i].value!=INT_MAX)
            cout<<str<<"---v"<<i+1<<"最短路径长度为: "<< dis[i].value <<"\n\t\t\t最短路径为: "<<dis[i].path<<endl;
        else {
            cout << dis[i].path << "当前没有最短路径" << endl;
        }}}

bool check(int Vexnum, int edge) {
    if (Vexnum <= 0 || edge <= 0 || ((Vexnum*(Vexnum - 1)) / 2) < edge)
        return false;
    return true;}

int main() {
    int vexnum=0; int edge=0; int sel=0; int s=0;
    while(1){
        cout<<"\n输入数字运行功能 \n 1.基于迪杰斯特拉算法最短路径计算 \n 2.基于和弗洛伊德算法最短路径计算 \n 3.Quit \n"<<endl;
        cin>>s;

        if(1==s){//迪杰斯特拉算法
            cout << "\n输入图的顶点个数和边的条数:('3 2'-“3顶点,2条线”)" << endl;
            cin >> vexnum >> edge;
            while (!check(vexnum, edge)) {
                cout << "输入的数值不合法,请重新输入" << endl;
                cin >> vexnum >> edge;}
            Graph_dis graph(vexnum, edge);
            graph.createGraph();
            graph.print();

            while(1){
                s=0;
                cout<< "\n 输入数字运行功能 \n 1.运行计算 \n 2.Quit \n" <<endl;
                cin>>s;
                if(1==s){
                    cout<< "请输入初始点,输入后将遍历所有节点最短距离:('1'-V1点出发到各点最短路径)" <<endl;
                    cin>>sel;
                    graph.Dijkstra(sel);
                    graph.print_path(sel);}
                else if(2==s){
                    break;
                }else{
                    cout<<"请输入正确值!"<<endl;
                }}}

        else if(2==s){//弗洛伊德算法
            cout << "输入图的顶点个数和边的条数:('3 2'-“3顶点,2条线”)" << endl;
            cin >> vexnum >> edge;
            while (!check(vexnum, edge)) {
                cout << "输入的数值不正确,请重新输入" << endl;
                cin >> vexnum >> edge;}
            Graph_fld graph(vexnum, edge);
            graph.createGraph(2);
            graph.print();

            while(1){
                s=0;
                cout<< "\n 输入数字运行功能 \n 1.运行计算 \n 2.Quit \n" <<endl;
                cin>>s;
                if(1==s){
                    cout<< "请输入初始点,输入后将遍历所有节点最短距离:('1'-V1点出发到各点最短路径)" <<endl;
                    cin>>sel;
                    graph.Floyd();
                    graph.print_path(sel);}else if(2==s){
                    break;
                }else{
                    cout<<"请输入正确值!"<<endl;
                }}}

        else if(3==s){//Quit
            cout<<"BYE!"<<endl;
            system("pause");
            return 0;
        }else{
            cout<<"请输入正确数字!"<<endl;
        }}}

  • 运行截图实例:

在这里插入图片描述
进行运算:

MENU:
在这里插入图片描述

Dijkstra:
在这里插入图片描述

Floyd

在这里插入图片描述

  • 在计算中发现迪杰斯特拉算法的缺陷,故推荐使用弗洛伊德算法进行线路优化计算!
  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 12
    评论
迪杰斯特拉算法(Dijkstra)是一种贪心算法,用于解决最短路径问题。它可以处理有权有向图或无向图,但不允许有负权边(权重必须为非负数)。 算法思路: 1. 从起点开始,初始化所有节点的距离为无穷大,起点距离为0; 2. 将起点加入“已访问”集合; 3. 对于起点的所有邻居节点,更新它们的距离(如果通过当前节点到达邻居节点的距离小于邻居节点原有的距离,则更新邻居节点的距离); 4. 从未访问集合中选择距离起点最近的节点,加入“已访问”集合; 5. 重复步骤3和4,直到所有节点都被加入“已访问”集合或者没有与起点相连的节点。 算法实现: Dijkstra算法的实现通常使用优先队列(PriorityQueue)来维护未访问集合中距离起点最近的节点。具体实现步骤如下: 1. 创建一个空的优先队列Q,将起点加入Q中,并设置起点到自身的距离为0; 2. 创建一个数组dist[],用于保存起点到各个节点的距离,初始化为无穷大; 3. 创建一个数组visited[],用于标记节点是否被访问过,初始化为false; 4. 将dist[起点]的值设置为0; 5. 当Q不为空时,重复以下步骤: a. 从Q中取出距离起点最近的节点u; b. 如果节点u已经被访问过,则跳过此次循环; c. 将节点u标记为已访问; d. 对于节点u的每个邻居节点v,如果节点v未被访问过并且通过节点u到达节点v的距离小于dist[v],则更新dist[v]的值; e. 将节点v加入Q中。 6. 最终,dist数组中保存的就是起点到各个节点的最短距离。 Dijkstra算法的时间复杂度为O(ElogV),其中E为边数,V为节点数。这是因为算法需要对每个节点的所有邻居节点进行遍历,而优先队列的插入和删除操作的时间复杂度为O(logV)。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

GodOuO

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

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

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

打赏作者

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

抵扣说明:

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

余额充值