dijkstra算法求單源最短路徑

#define MAXINT 0xfff
#define MAXSIZE 1000
#include<iostream>
#include<string>
using namespace std;

int amapBorder[MAXSIZE][MAXSIZE];
int vNum = 6;		//總共有6個頂點元素

void initmap()		//這裏是無向圖,初始化隨便造了一個圖,沒有用存儲圖的結構,存儲圖的結構我其他文章裏有。
{
	for(int i = 1 ; i < vNum + 1 ; i++)
	{
		for(int j = 1 ; j < vNum + 1 ; j++)
		{
			amapBorder[i][j] = MAXINT;	//先初始化圖的所有邊都爲無窮大,即沒有邊。
		}
	}

	amapBorder[1][2] = 6;
	amapBorder[1][3] = 3;
	amapBorder[2][3] = 2;
	amapBorder[2][4] = 5;
	amapBorder[3][4] = 3;
	amapBorder[3][5] = 4;
	amapBorder[4][5] = 2;
	amapBorder[4][6] = 3;
	amapBorder[5][6] = 5;		//定義一部分邊,並給出邊權重
	for(int i = 1 ; i < vNum + 1 ; i++)
	{
		for(int j = 1 ; j < vNum + 1 ; j++)
		{
			if(i == j)
			{
				amapBorder[i][j] = 0;	//頂點與它自身的權重肯定爲0
			}
			if(amapBorder[i][j] == MAXINT)
			{
				amapBorder[i][j] = amapBorder[j][i];	//由於是無向圖,所以兩個頂點之間的邊無論什麼方向,權重一樣

			}
		}
	}
}

void dijstra(int vo)
{
	int U[7] = {0} 		//初始化U數組和dist數組所有元素爲0,U[]數組判斷一個頂點是否已經加入得出最短距離的陣營,
	int dist[7] = {0};	//dist[]存儲所有頂點到給定點vo最短距離
	int path[7];		//存儲該頂點(數組下標)對應的上一個頂點,通過它可以遞歸得出到達該頂點所經過的所有頂點,連起來也就是最短路徑。
	/*其實總共是有6個頂點元素的,這裏數組下標0沒有用到,資源浪費了,不過強迫症,不想用0,渴望從1開始*/
	for(int i = 1 ; i < vNum + 1 ; i++)	//vNum+1是7
	{
		dist[i] = amapBorder[vo][i];	//dist[i]這裏保存vo-i所經距離,這時候我不知道最短距離,所以先取鄰接矩陣裏的信息,可能是0,可能是數字n,可能是無窮大
		if(dist[i] == MAXINT)	
		{
			path[i] = -1;	//如果是正無窮,意味着此時,vo到達不了i,沒路,那麼到達i所經歷的最後一個頂點有嗎?沒有,那就給個-1吧,此路不通。

		}
		else
		{
			path[i] = vo;	//如果有路,那就正常把經過i的最後一個頂點賦給path[i],方便最後遞歸找路。
		}
	}

	
	
	for(int i = 1 ; i < vNum + 1 ; i ++)
	{
		int minNum = MAXINT;	//選取出來dist[j]的最小值並把記錄。
		int temp = vo;		
		for( int j = 1 ; j < vNum + 1 ; j++)
		{
			if((!U[j]) && dist[j] < minNum )	//判斷要求:此時j這個點要在沒得到最小路徑點的陣營裏,並且這個dist[j]小於minNum
			{
				minNum = dist[j];		//從而篩選出最小的dist[]
				temp = j;			//記錄最小的dist[]所對應的頂點,j賦值給temp;
			}
		}
		U[temp] = 1;		//temp點已找到最短距離,加入找到陣營

		for(int j = 1; j < vNum + 1 ; j++)
		{
			if(!U[j] && amapBorder[temp][j] < MAXINT)	//判斷要求:j在未找到陣營裏,且temp-j有路可走,其實有路可走不判斷也行,主要害怕MAXINT這個數太大跟dist[temp]相加溢出。
			{
				if(dist[j] > amapBorder[temp][j] + dist[temp])	//如果vo到temp的距離(最短距離)+ temp到j的距離 比原來vo直接到j距離短,則更新dist[j]
				{
					dist[j] = amapBorder[temp][j] + dist[temp];
					path[j] = temp;		//記錄path[j]經過的最後一個點,至少當前這個點事temp,以後可能還要變。
				}
			}
		}
	}
	
	for(int i = 1; i < vNum + 1 ; i++)	//打印vo到各個頂點最短距離,以及路徑
	{
		cout << i << ":	" << dist[i] << '\t';
		int j = i;
		cout << j << "<-";
		while(path[j] != vo)	//遞歸path[]找出到一個頂點經過的所有頂點,倒序列出來,當然可以轉換爲正序。
		{
			j = path[j];
			cout << j << "<-";
		}
		cout << vo << endl;
	}
}

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