(c++)数据结构与算法之图:Dijkstra、Floyd算法、判断有向图回路

//带权有向图的最短路径算法:Dijkstra、Floyd(结果和输出分开)
//判断在给定有向图中是否存在一个有向回路

#include<set>
#include <iostream>
#define MAXE 100
#define MAXV 15
#define MAXWEIGHT 1000
#define INF 1000
using namespace std;
class graph
{
private:
    int **matrix,*mark;
    int vNum,eNum;
public:
    graph(){};
    graph(int v)
    {
        if(v>=MAXV)    cout<<"construct false"<<endl;
        vNum=v;
        eNum=0;
        mark=new int[vNum];
        for(int i=0;i<vNum;i++)
            mark[i]=0;
        matrix=new int*[vNum];
        int i,j;
        for(i=0;i<vNum;i++)
            matrix[i]=new int[vNum];
        for(i=0;i<vNum;i++)
            for(j=0;j<vNum;j++)
                matrix[i][j]=INF;
    }
    void showEdge()                     //展示邻接矩阵
    {
        cout<<"邻接矩阵如下: "<<endl;
        for(int i=0;i<vNum;i++)
            for(int j=0;j<vNum;j++)
            {
                cout<<matrix[i][j]<<"   ";
                if(j==vNum-1)      cout<<endl;
            }
    }
    void resetMark()                    //重置节点标记数组
    {
        for(int i=0;i<vNum;i++)
            mark[i]=0;
    }
    void setEdge(int start,int end,int weight)
    {
        if(weight>=MAXWEIGHT)       return;
        if(matrix[start][end]==0)
        {
            eNum++;
        }
        matrix[start][end]=weight;
    }
    int * * Dijkstra(int s)                      //Dijkstra:求点s到其余各点的最短路径
    {
        int n=vNum;                           //结点个数
        int *d=new int[n];                    //存放s到各个结点的路径长度(相对最短)(自身到自身为INF)
        int *path=new int[n];                 //存放已确定最短路径的结点的前驱结点(用于输出)
        set<int> S,V;                         //S=已知最短路径的点集,V=未求出最短路径的点集
        set<int>::iterator itr;
        S.insert(s);                          //插入首个结点
        {                                     //初始化d、path、V
            for(int i=0;i<n;i++)
                d[i]=matrix[s][i];
            for(int i=0;i<n;i++)
                path[i]=i;
            for(int i=0;i<n;i++)
                V.insert(i);
            V.erase(s);
        }
        while(!V.empty())                       //当V空,即所有点最短路径已求出时说明完成
        {
            int minWeight=INF,k;                //k为未求出最短路径的结点中到s权重最小的
            for(int i=0;i<n;i++)                //找到k
            {
                if((itr=S.find(i))!=S.end())      continue;
                if((itr=V.find(i))!=V.end()&&d[i]<=minWeight)
                {
                    minWeight=d[i];
                    k=i;
                }
            }
            if(d[k]==matrix[s][k])      path[k]=s;//更新前驱
            V.erase(k);
            S.insert(k);
            for(int j=0;j<n;j++)                //根据找到的k更新最短路径
            {
                if(j==s)       d[j]=0;
                else if(d[k]+matrix[k][j]<d[j])
                {
                    d[j]=matrix[k][j]+d[k];
                    path[j]=k;
                }
            }
        }
        int **a=new int*[2];
        a[0]=new int[n];
        a[1]=new int[n];
        for(int i=0;i<n;i++)
        {
            a[0][i]=d[i];
            a[1][i]=path[i];
        }
        delete [] d;
        delete [] path;
        return a;
    }
    int * * Floyd()                                //Floyd:求任意两点间的最短路径
    {
        int n=vNum;
        int **adj=new int*[n],**path=new int*[n];
        for(int i=0;i<n;i++)
        {
            adj[i]=new int[n];
            path[i]=new int[n];
        }
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                adj[i][j]=matrix[i][j];
        int i,j,k;
        for(k=0;k<n;k++)
            for(i=0;i<n;i++)
                for(j=0;j<n;j++)
                    if(adj[i][j]>adj[i][k]+adj[k][j])
                    {
                        adj[i][j]=adj[i][k]+adj[k][j];
                        path[i][j]=k;
                    }
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                if(i==j) adj[i][j]=INF;
        return adj;
    }
    void showDijkstra(int s)                    //两个函数结果的展示:
    {
        int **d=Dijkstra(s),n=vNum;
        cout<<s<<"的最小生成树:"<<endl;
            for(int i=0;i<n;i++)
            {
                if(i==s)    continue;
                if(d[1][i]==s)  cout<<s<<" --> "<<i<<" --> ("<<d[0][i]<<")"<<endl;
                else
                {
                    int a[n];
                    for(int j=0;j<n;j++)
                        a[j]=-1;
                    int p=d[1][i],j=n-1;
                    while(p!=s)
                    {
                        a[j--]=p;
                        p=d[1][p];
                    }
                    a[j]=s;
                    while(j<n)
                        cout<<a[j++]<<" --> ";
                    cout<<i<<" --> ("<<d[0][i]<<")"<<endl;
                }
            }
    }
    void showFloyd()
    {
        int **adj=Floyd();
        cout<<"顶点对之间的最短距离:"<<endl;
        for(int i=0;i<vNum;i++)
            for(int j=0;j<vNum;j++)
            {
                cout<<adj[i][j]<<"        ";
                if(j==vNum-1)      cout<<endl;
            }
    }
    void isCircle()                             //基于Floyd算法的判断有向图是否为回路
    {
        int n=vNum,**adj=Floyd(),i,j;           //得到Floyd的结果
        for(i=0;i<n;i++)                        //两层循环找到一个i到j有路径且j到i有路径的i、j
        {
            for(j=0;j<n;j++)
                if(adj[i][j]<INF&&adj[j][i]<INF)
                    break;
            if(adj[i][j]<INF&&adj[j][i]<INF)
                    break;
        }
        if(i==n&&j==n)
            cout<<"图中没找到有向回路"<<endl;
        else                                    //找到则输出:输出方法和showDijkstra一致,
        {                                       //通过两个数组(前驱、权重)来输出路径
            cout<<"找到有向回路为:"<<endl;
            int **d=Dijkstra(i);
            if(d[1][j]==i)  cout<<" --> "<<i<<" --> "<<j;
            else
            {
                int a[n];
                for(int j=0;j<n;j++)
                    a[j]=-1;
                int p=d[1][j],k=n-1;
                while(p!=i)
                {
                    a[k--]=p;
                    p=d[1][p];
                }
                a[k]=i;
                while(k<n)
                    cout<<" --> "<<a[k++];
                cout<<" --> "<<j;
            }
            cout<<endl;
            int **d2=Dijkstra(j);
            if(d2[1][i]==j)  cout<<" --> "<<j<<" --> "<<i<<endl;
            else
            {
                int a[n];
                for(int j=0;j<n;j++)
                    a[j]=-1;
                int p=d2[1][i],k=n-1;
                while(p!=j)
                {
                    a[k--]=p;
                    p=d2[1][p];
                }
                a[k]=j;
                while(k<n)
                    cout<<" --> "<<a[k++];
                cout<<" --> "<<i<<endl;
            }
        }
    }

};
int main()
{
    graph g(6);
    graph g1(6);
    {//set edge (P170 4-18)
        g.setEdge(0,4,30);
        g.setEdge(0,1,12);
        g.setEdge(1,2,5);
        g.setEdge(0,2,10);
        g.setEdge(2,3,50);
        g.setEdge(0,5,100);
        g.setEdge(4,5,60);
        g.setEdge(4,3,20);
        g.setEdge(3,5,10);
        g1.setEdge(0,4,30);
        g1.setEdge(0,1,12);
        g1.setEdge(1,2,5);
        g1.setEdge(0,2,10);
        g1.setEdge(2,3,50);
        g1.setEdge(0,5,100);
        g1.setEdge(4,5,60);
        g1.setEdge(4,3,20);
        g1.setEdge(3,5,10);
        g1.setEdge(5,0,10);
    }
    //展示Dijkstra算法
    g.showEdge();
    g.Dijkstra(0);
    g.Dijkstra(1);
    g.Dijkstra(2);
    g.Dijkstra(3);
    g.Dijkstra(4);
    g.Dijkstra(5);
    g.showDijkstra(5);
    //展示floyd算法
    g.showFloyd();
    g1.showEdge();
    g1.showFloyd();
    g1.isCircle();
    cout << "Hello world!" << endl;
    return 0;
}

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