prime算法和dijkstra算法的主要區別,以及實現


prime算法參考點擊打開鏈接http://blog.csdn.net/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 :



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章