prime算法参考点击打开链接http://blog.youkuaiyun.com/yeruby/article/details/38615045
1. prime算法和dijkstra算法的主要区别
Dijkstra算法的对象无所谓是有向图还是无向图,它可以求单源最短路径(一个点到其余各点的最短路径),时间复杂度为O(n*n)。非常相似prime算法,只有一个区别,
核心思想就是更新连接路径时,prime中是跟踪接下来的结点到生成树中的最小交叉边,而dijkstra中是跟踪接下来的结点到
起点所有经过的结点的路径和,这样说不太好理解,
以下图举个例子(只分析v5):初始化后(以v1为起点),在prime中,v5原本连在v1上(v5路径长度为无穷),第一次更新路径时,v5连在v3上(v5路径长度为6),同样的条件下,在dijkstra中,v5原本连在v1上(v5路径长度为无穷)也变为连在v3上,可是路径长度变为7(1+6),这就是两者的区别了!
2. 代码实现
#include<iostream>
#include<fstream>
#define max 100
#define infinity 0x7fffffff
using namespace std;
struct MinPath
{
int path;//该边所对应的起点(存放路径)
double lowcost;//该边终点所对应的权值(存放路径长度)
bool test;//判断该点是否已找到从起点到它的最短路径
};
class MGraph
{
public:
MGraph();
double Dijstra(int v);
void dfspath(int i,int v);//回溯起点v到终点i的最短路径
void PrintPath(int v);//打印起点v到各点的最短路径
private:
int graph[max][max];
int vexnum,edgenum;double sumcost;//分别为总结点数,总边数,最小路径权值和
MinPath *minpath;
};
MGraph::MGraph():sumcost(0)
{
int i,j,lowcost;
ifstream in("data.txt");
if(!in.fail())
{
in>>vexnum>>edgenum;
for( i=1;i<=vexnum;++i)
{
for(j=1;j<=vexnum;++j)
{
if(i==j)
{
graph[i][j]=0;
}
else
graph[i][j]=infinity;
}
}
for(int k=1;k<=edgenum;++k)//赋值有连接的边
{
in>>i>>j>>lowcost;
graph[i][j]=graph[j][i]=lowcost;
}
}
in.close();
}
double MGraph::Dijstra(int v)
{
minpath=new MinPath[vexnum+1];
for(int i=1;i<=vexnum;++i)
{
minpath[i].path=v;
minpath[i].lowcost=graph[v][i];
minpath[i].test=false;
}
minpath[v].test=true;
for(int i=2;i<=vexnum;++i)//第一个点已加入,剩下还要加vexnum-1个
{
int minid=0;minpath[minid].lowcost=infinity;
for(int j=1;j<=vexnum;++j)
{
if(!minpath[j].test&&minpath[minid].lowcost>minpath[j].lowcost)
minid=j;
}
cout<<"V"<<v<<"-->V"<<minid<<"="<<minpath[minid].lowcost<<endl;
sumcost+=minpath[minid].lowcost; minpath[minid].test=true;
for(int j=1;j<=vexnum;++j)
{
if(!minpath[j].test&&minpath[minid].lowcost+graph[minid][j]<minpath[j].lowcost)
{
minpath[j].lowcost=minpath[minid].lowcost+graph[minid][j];
minpath[j].path=minid;
}
}
}
return sumcost;
}
void MGraph::dfspath(int i,int v)
{
if(v==i)
return ;
else
{
int j=i;
i=minpath[i].path;//回溯,i是j前面一个数
dfspath(i,v);
if(v==i)
cout<<"V"<<i<<"-->V"<<j;
else
cout<<"-->V"<<j;
}
}
void MGraph::PrintPath(int v)
{
for(int i=1;i<=vexnum;++i)
{
if(i!=v)
{
dfspath(i,v);
cout<<endl;
}
}
}
int main()
{
MGraph mg;int v;
cout<<"请输入起点序号v";
cin>>v;
cout << "最小权值和="<<mg.Dijstra(v)<<endl;
cout<<"单源最短(完整)路径:"<<endl;
mg.PrintPath(v);
return 0;
}
强调一点,单源最短路径的输出用到了回溯的方法,从尾到头的输出很容易让人犯浑,主要就是搞清楚每次递归时的起点和终点就行!
3. 调试
Output :