DijKstra算法C++详解

先放代码

  /*迪杰斯特拉算法*/
  
#include<iostream>
#include<iomanip>
using namespace std;
#define INFINITY INT_MAX
#define MAX_VERTEX_NUM 20
#define TRUE 1
#define FALSE 0
#define OK 1
typedef struct ArcCell{
	unsigned int adj;		//权值 
}ArcCell , AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; 

typedef struct{
	char vex;
	int location;
}Vexs;

typedef struct{
	Vexs vexs[MAX_VERTEX_NUM];
	AdjMatrix arcs;
	int vexnum,arcnum;
}MGraph;

MGraph G;

void show(MGraph G, int n){
	cout<<"the graph G :"<<endl;
	cout<<"  ";
	for(int i = 0; i < n; ++i) 
		cout<<std::left<<setw(8)<<G.vexs[i].vex<<ends;
	cout<<endl;
	for(int i = 0; i < n; ++i){
		cout<<G.vexs[i].vex<<ends;
		for(int j = 0; j < n; ++j)
			if(G.arcs[i][j].adj == INFINITY)
				cout<<std::left<<setw(9)<<"0";
			else
				cout<<std::left<<setw(9)<<G.arcs[i][j].adj;
		cout<<endl;
	}	
}

int LocateVex(MGraph &G, char v){
	for(int i = 0; i < G.vexnum; ++i)
		if(G.vexs[i].vex == v)
			return G.vexs[i].location;
}

char LocateLocation(int v0){
	for(int i = 0; i < G.vexnum; ++i)
		if(G.vexs[i].location == v0)
			return G.vexs[i].vex;
}

void showShortPash(int D[], int n, int v0){
	cout<<"  ";
	char v = LocateLocation(v0);
	for(int i = 0; i < n; ++i)
		if(G.vexs[i].vex != v)
			cout<<setw(8)<<G.vexs[i].vex;
	cout<<endl;
	cout<<v<<ends;
	for(int i = 0; i < n; ++i)
		if(i != v0)
			cout<<std::left<<setw(8)<<D[i];
	cout<<endl<<"-------------------------------------"<<endl;
}

int CreatUDN(MGraph &G,int &n){
	cout<<"Input the Number of Vex and Arc Directionless Network."<<endl;
	cout<<"Vex number : ";
	cin>>G.vexnum;
	n = G.vexnum;
	cout<<"Arc number : ";
	cin>>G.arcnum;
	cout<<"Input Vertex Calibration."<<endl;
	for(int i = 0; i < G.vexnum; ++i){
		cout<<"Calibration of the "<<i<<" vertex : ";
		cin>>G.vexs[i].vex;
		G.vexs[i].location = i;
	}
	for(int i = 0; i < G.vexnum; ++i)
		for(int j = 0; j < G.vexnum; ++j)
			G.arcs[i][j] = {INFINITY};
	cout<<"Enter the vertices and weights of an arc dependency : "<<endl;
	for(int k = 0; k < G.arcnum; ++k){
		char v1,v2;
		int w,i,j;
		cin>>v1>>v2>>w;
		i = LocateVex(G,v1);
		j = LocateVex(G,v2);
		G.arcs[i][j].adj = w;
		G.arcs[j][i] = G.arcs[i][j];
	}
	return OK;
}//CreatUDN

			/*迪杰斯特拉算法*/
void ShortestPath_DIJ(MGraph G, int v0, bool **P, int D[], int n){
	//用DijKstra算法求无向网G的v0顶点到其余顶点v的最短路径P[v]及其带权长度D[v]。 
	//若P[v][w]为true,则w是从v0到v当前求得的最短路径上的顶点。 
	//final[v]为true当且仅当v∈S,即已经求得从v0到v的最短路径。 
	bool final[n];
	unsigned int i,v,w,min;
	for(v = 0; v < G.vexnum; ++ v){
		final[v] = FALSE;
		D[v] = G.arcs[v0][v].adj;	
		for(w = 0; w < G.vexnum; ++ w)
			P[v][w] = FALSE;    //设空路径
		if(D[v] < INFINITY){
			P[v][v0] = TRUE;
			P[v][v] = TRUE;
		} 
	} //for
	D[v0] = 0;
	final[v0] = TRUE;       //初始化,v0顶点属于S集
	//开始主循环,每次求得v0到某个顶点v的最短路径,并加v到S集
	for(i = 1; i < G.vexnum; ++ i){		//其余G.vexnum-1个顶点
		min = INFINITY; 				//当前所知离v0顶点的最近距离 	
		for(w = 0; w < G.vexnum; ++ w)
			if(!final[w])				//w顶点在V-S中 
				if(D[w] < min){
					v = w;
					min = D[w];
				}					//w顶点离v0顶点更近 
		final[v] = TRUE;				//离v0顶点最近的v加入S集
		for(w = 0; w < G.vexnum; ++ w)	//更新当前最短路径及距离
			if(!final[w] && ((min + G.arcs[v][w].adj) < D[w])){
				//修改D[w]和P[w],w∈V-S
				D[w] = min + G.arcs[v][w].adj;
				P[w] = P[v];
				P[w][w] = TRUE;   		//P[w] = P[v] + P[w]
			} //if
	} //for
} //ShortestPath_DIJ 

详解
首先是图的结构
typedef struct ArcCell{
unsigned int adj; //权值
}ArcCell , AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];

typedef struct{
	char vex;
	int location;
}Vexs;

typedef struct{
	Vexs vexs[MAX_VERTEX_NUM];
	AdjMatrix arcs;
	int vexnum,arcnum;
}MGraph;

ArcCell用来存放边的信息,本文只涉及权值,如果有其他信息也可以添加
Vexs是点的信息,因为实验中需要根据下标和其他存储信息的数组联系起来,所以加了一个location用来表示点在图中的下标;vex是点的名称,如有具体实际意义可以改为string型
Mgraph就是图了,图中包含一个顶点数组,一个邻接矩阵,两个整型变量表示点数和变数

void show(MGraph G, int n){
    	cout<<"the graph G :"<<endl;
    	cout<<"  ";
    	for(int i = 0; i < n; ++i) 
    		cout<<std::left<<setw(8)<<G.vexs[i].vex<<ends;
    	cout<<endl;
    	for(int i = 0; i < n; ++i){
    		cout<<G.vexs[i].vex<<ends;
    		for(int j = 0; j < n; ++j)
    			if(G.arcs[i][j].adj == INFINITY)
    				cout<<std::left<<setw(9)<<"0";
    			else
    				cout<<std::left<<setw(9)<<G.arcs[i][j].adj;
    		cout<<endl;
    	}	
    }

就是一个控制输出格式,输出整张图的函数,没得讲。

	int LocateVex(MGraph &G, char v){
    	for(int i = 0; i < G.vexnum; ++i)
    		if(G.vexs[i].vex == v)
    			return G.vexs[i].location;
    }
    
    char LocateLocation(int v0){
    	for(int i = 0; i < G.vexnum; ++i)
    		if(G.vexs[i].location == v0)
    			return G.vexs[i].vex;
    }

LocateVex就是根据你输入的点的名称锁定到这个点对应的下标的函数
LocateLocation是根据输入的下标找到这个点的名称的函数

void showShortPash(int D[], int n, int v0){
    	cout<<"  ";
    	char v = LocateLocation(v0);
    	for(int i = 0; i < n; ++i)
    		if(G.vexs[i].vex != v)
    			cout<<setw(8)<<G.vexs[i].vex;
    	cout<<endl;
    	cout<<v<<ends;
    	for(int i = 0; i < n; ++i)
    		if(i != v0)
    			cout<<std::left<<setw(8)<<D[i];
    	cout<<endl<<"-------------------------------------"<<endl;
    }

输出到各点的最短距离,也都是格式调整的问题,没啥好说的。

 int CreatUDN(MGraph &G,int &n){
    	cout<<"Input the Number of Vex and Arc Directionless Network."<<endl;
    	cout<<"Vex number : ";
    	cin>>G.vexnum;
    	n = G.vexnum;
    	cout<<"Arc number : ";
    	cin>>G.arcnum;
    	cout<<"Input Vertex Calibration."<<endl;
    	for(int i = 0; i < G.vexnum; ++i){
    		cout<<"Calibration of the "<<i<<" vertex : ";
    		cin>>G.vexs[i].vex;
    		G.vexs[i].location = i;
    	}
    	for(int i = 0; i < G.vexnum; ++i)
    		for(int j = 0; j < G.vexnum; ++j)
    			G.arcs[i][j] = {INFINITY};
    	cout<<"Enter the vertices and weights of an arc dependency : "<<endl;
    	for(int k = 0; k < G.arcnum; ++k){
    		char v1,v2;
    		int w,i,j;
    		cin>>v1>>v2>>w;
    		i = LocateVex(G,v1);
    		j = LocateVex(G,v2);
    		G.arcs[i][j].adj = w;
    		G.arcs[j][i] = G.arcs[i][j];
    	}
    	return OK;
    }//CreatUDN

一些输入输出提示让你创建一个图的函数

下面就是重点部分了,DijKstra算法核心

void ShortestPath_DIJ(MGraph G, int v0, bool **P, int D[], int n){
    	//用DijKstra算法求无向网G的v0顶点到其余顶点v的最短路径P[v]及其带权长度D[v]。 
    	//若P[v][w]为true,则w是从v0到v当前求得的最短路径上的顶点。 
    	//final[v]为true当且仅当v∈S,即已经求得从v0到v的最短路径。 
    	bool final[n];
    	unsigned int i,v,w,min;
    	for(v = 0; v < G.vexnum; ++ v){
    		final[v] = FALSE;
    		D[v] = G.arcs[v0][v].adj;	
    		for(w = 0; w < G.vexnum; ++ w)
    			P[v][w] = FALSE;    //设空路径
    		if(D[v] < INFINITY){
    			P[v][v0] = TRUE;
    			P[v][v] = TRUE;
    		} 
    	} //for
    	D[v0] = 0;
    	final[v0] = TRUE;       //初始化,v0顶点属于S集
    	//开始主循环,每次求得v0到某个顶点v的最短路径,并加v到S集
    	for(i = 1; i < G.vexnum; ++ i){		//其余G.vexnum-1个顶点
    		min = INFINITY; 				//当前所知离v0顶点的最近距离 	
    		for(w = 0; w < G.vexnum; ++ w)
    			if(!final[w])				//w顶点在V-S中 
    				if(D[w] < min){
    					v = w;
    					min = D[w];
    				}					//w顶点离v0顶点更近 
    		final[v] = TRUE;				//离v0顶点最近的v加入S集
    		for(w = 0; w < G.vexnum; ++ w)	//更新当前最短路径及距离
    			if(!final[w] && ((min + G.arcs[v][w].adj) < D[w])){
    				//修改D[w]和P[w],w∈V-S
    				D[w] = min + G.arcs[v][w].adj;
    				P[w] = P[v];
    				P[w][w] = TRUE;   		//P[w] = P[v] + P[w]
    			} //if
    	} //for
    } //ShortestPath_DIJ 

分块详解
D[v]是从给定顶点到其余顶点v的带权长度
P[v][w]为true,则w是从v0到v当前求得的最短路径上的顶点。
final[v]为true当且仅当v∈S,即已经求得从v0到v的最短路径。

for(v = 0; v < G.vexnum; ++ v){
    		final[v] = FALSE;
    		D[v] = G.arcs[v0][v].adj;	
    		for(w = 0; w < G.vexnum; ++ w)
    			P[v][w] = FALSE;    //设空路径
    		if(D[v] < INFINITY){
    			P[v][v0] = TRUE;
    			P[v][v] = TRUE;
    		} 
    	} //for
    	D[v0] = 0;
    	final[v0] = TRUE;       //初始化,v0顶点属于S集

第一个for循环就是
将所有final初始化为FALSE
将所有D[v]设为邻接表中v0到v的值
将所有P初始化为FALSE,但是从v0到v的路径必然包括v0和v本身,所以将P[v][v0],P[v][v]设为TRUE
给定起始点到自身必然距离为0,且已有最短路,所以final[v0]设为TRUE,D[v0]设为0
第二个大的for循环就是找出其余n-1个点最短路径的

min = INFINITY; 				//当前所知离v0顶点的最近距离 	
    		for(w = 0; w < G.vexnum; ++ w)
    			if(!final[w])				//w顶点在V-S中 
    				if(D[w] < min){
    					v = w;
    					min = D[w];
    				}					//w顶点离v0顶点更近 
    		final[v] = TRUE;				//离v0顶点最近的v加入S集

第二个大的for循环里有两个小的嵌套的for循环
第一个如上,就是比较所有D[v],找到除了已经找到最短路径的点外其他点D[v]最小的点。
找到后就设为最短路径。

for(w = 0; w < G.vexnum; ++ w)	//更新当前最短路径及距离
    			if(!final[w] && ((min + G.arcs[v][w].adj) < D[w])){
    				//修改D[w]和P[w],w∈V-S
    				D[w] = min + G.arcs[v][w].adj;
    				P[w] = P[v];
    				P[w][w] = TRUE;   		//P[w] = P[v] + P[w]
    			} //if
    	} //for

在上一个循环找出的最短路径的基础上更新其他点的D[v],如果经过已经找到的最短路径上的点到该点比原来到该点更近则更新D[v]。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值