//带权有向图的最短路径算法: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;
}
(c++)数据结构与算法之图:Dijkstra、Floyd算法、判断有向图回路
原文作者:Dijkstra算法
原文地址: https://blog.csdn.net/CSDNMARKT/article/details/78878972
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
原文地址: https://blog.csdn.net/CSDNMARKT/article/details/78878972
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。