迪杰斯特拉算法详解

1.概述:Dijkstra算法是用来寻找两点之间最短路径的算法,在实际生活中有着很大的作用他的思想就是选定一点然后向后遍历直至所有点到选定点的最短距离全部求处为止。
2.算法思想:
(1)初始化:先找处从源点V0到各终点Vk的直达路径(V0,Vk),即通过一条弧到达的路径。
(2)选择:从这些路径中找出一条长度最短的路径(V0,u)。
(3)更新:然后对其余各条路径进行适当的调整:
若在图中存在弧(u,Vk),且(u,Vk)+(V0,u)<(V0,Vk),则以路径(V0,u,Vk)代替(V0,Vk)。

(4)在调整后的各条路径中,再找长度最短的路径,以此类推。
代码及注释如下:
3.算法实现图示:
迪杰斯特拉算法详解_第1张图片
1.数据结构及其初始化:

#include 
#include 
#include 
#include 
#include 
#include 

#define N 100
#define INITFITE 32767
using namespace std;

typedef struct Node{
	int vernum,arcnum;
	char data[N];
	int martrix[N][N];
}Graph;

struct NNode{
	int pree;  //存储该节点的前驱节点!
	int lowcost;//存储到该节点的最短路程!
}closedge[N];

int locate(Graph G,char ch)
{
	int i;
	for (int i = 0;i < G.vernum;i++)
	{
		if (G.data[i] == ch)
		return i;
	}
}

2.邻接矩阵的建立:

void create_Graph(Graph &G)
{
	char v1,v2;
	int weight;
	cout<<"please key in the vernum & arcnum"<<endl;
	cin>>G.vernum>>G.arcnum;
	cout<<"please key in all the vertexs"<<endl;
	for (int i = 0;i < G.vernum;i++)
	cin>>G.data[i];
	cout<<"please key in the v1 & v2 & weight"<<endl;
	for (int i = 0;i < G.vernum;i++)
	for (int j = 0;j < G.vernum;j++)
	G.martrix[i][j] = INITFITE;
	for (int ii = 0;ii < G.arcnum;ii++)
	{
		cin>>v1>>v2>>weight;
		int i = locate(G,v1);
		int j = locate(G,v2);
		G.martrix[i][j] = weight;
	}
}

3.Dijkstra算法及显示路径函数:

bool visited[N];
void DIJ(Graph G,char ch)
{
	int v = locate(G,ch);//找到源点在字符数组中的位置
	int w;
	visited[v] = true;
	closedge[v].pree = -1;//源点的前驱置成-1;
	int min = 1000000;
	for (int i = 0;i < G.vernum;i++)//----------初始化
	{	
		closedge[i].lowcost = G.martrix[v][i];
		if (!visited[i])
		{
			if (closedge[i].lowcost < INITFITE) //如果成立,则说明有直达边。
			closedge[i].pree = v;//则将前驱置成v;
			else //否则没有直达边
			closedge[i].pree = -1;//则将前驱置成-1;
			if (closedge[i].lowcost < min) //寻找最小的边!!
			{
				w = i;
				min = closedge[i].lowcost;
			}
		}
		cout<<closedge[i].lowcost<<endl; //打印初始化后的到各点的最短距
	}
	cout<<"----------------"<<endl; 
	closedge[w].pree = v;
	for (int j = 0;j < G.vernum - 1;j++) //---------更新
	{
		v = w;
		visited[v] = true; //已经确定的点置成true;
		min = 1000000;
		for (int i = 0;i < G.vernum;i++)
		{		
			if (!visited[i])
			{
				if (closedge[v].lowcost + G.martrix[v][i] < closedge[i].lowcost) // 如果由于D.data[v]的引入导致到G.data[i]的距离改变,则将最短路径赋成改变后的新值,将前驱赋成v;
				{
					closedge[i].lowcost = closedge[v].lowcost + G.martrix[v][i];
					closedge[i].pree = v;	
				}
				if (closedge[i].lowcost < min) //找到最小的边
				{
					w = i;
					min = closedge[i].lowcost;
				}
			}//cout<<"&&"<
			cout<<closedge[i].lowcost<<endl;//打印该次更新后的情况
		}	
		cout<<"----------------"<<endl; 
		//cout<
		//closedge[w].pree = v;
		//closedge[w].lowcost = min;
	}
}

void show(Graph G,char ch)
{
	int v = locate(G,ch);
	char ans[N];
	int j,k;
	for (int i = 0;i < G.vernum;i++)
	{
		memset(ans,0,sizeof(ans));
		//cout<
		k = i;
		if (closedge[i].pree == -1 && i != v)
		{
			cout<<ch<<"--->"<<G.data[i]<<":";
			cout<<"There is no way"<<" "<<closedge[i].lowcost<<endl;
			
			continue;
		}
		else if (closedge[i].pree == -1 && i == v)
		{
			cout<<ch<<"--->"<<G.data[i]<<":";
			cout<<G.data[v]<<" "<<G.data[v]<<" "<<0<<endl;
			continue;
		}
		else
		{
			j = 0;
			ans[j] = G.data[k];
			while (closedge[k].pree != v) //妈耶 问题出在这里 调了半天 小循环不要与外边的循环控制变量一样!!!此处控制条件十分巧妙! 
			{
				ans[++j] = G.data[closedge[k].pree];
				k = closedge[k].pree;
			}
			ans[++j] = G.data[v];
		}
		for (int i1 = 0;i1 <= j / 2;i1++)//导致得到的序列
		{
			swap(ans[i1],ans[j - i1]);
		}
		cout<<ch<<"--->"<<G.data[i]<<":";
		for (int i2 = 0;i2 <= j;i2++)
		{
			cout<<ans[i2]<<" ";
		}
		cout<<closedge[i].lowcost<<endl;
		//cout<
	}
}

4.主函数:

int main(){
	Graph G;
	create_Graph(G);
	for (int i = 0;i < G.vernum;i++)
	{
		for (int j = 0;j < G.vernum;j++)
		printf ("%7d ",G.martrix[i][j]);
		cout<<endl;
	}
	memset(visited,false,sizeof(visited));
	DIJ(G,'B');
	show(G,'B');
	return 0;
}
/*A C 10
A F 100
A E 30
B C 5
C D 50
D F 10
E D 20
E F 60*/

例:(求B点到其他点的最短路径)
迪杰斯特拉算法详解_第2张图片
运行结果:
迪杰斯特拉算法详解_第3张图片
迪杰斯特拉算法是求某一个点到其他点的最短距离的算法,考研要求掌握!!而各点到其他点的最短距离的算法是弗洛伊德算法,考研要求没有那么严格!但是要求会手工操作!

你可能感兴趣的:(数据结构)