Dijastra最优路径算法

原创 2015年07月08日 21:38:54

关于Dijastra算法,零零散散地研究了差不多两天了,基本上弄懂了它的思路和写程序的思路。算法思路不是很难(没理解时还是觉得有点晦涩),代码的实现过程,需要反复推敲和琢磨。目前先写个初级版本(现在暂时只理解到这个程度)

算法的思想和方法,各路牛人已经写过很多,小菜鸟就不赘述了,对我自己而言,我觉得下面的思路有助于我的理解,写上来:

首先上一个无向图,以及对应的Dijastra算法过程(来源http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html我在理解时,也参考了这篇文章)



大致思路,首先选取源结点A,将除源节点以外的其他结点分到U集合中,然后从A开始,遍历与它直接相邻的结点,选取路径AC最短,故C结点做为下一次的起始点。上面的表,对于这个过程描述得很清楚。看完这个,算法的思想大致就理解了。但是对于代码,还是有一定距离的。下面是我手写的,对于这个算法,代码大致的思路



完整代码C++实现:

<pre name="code" class="cpp">#include<iostream>
#include<iomanip>
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <list>
#include<vector>

using namespace std;

const int MAX_required = 505;//城市数量最大值
const int Max_int = 0x7fffffff;//城市间没有路径时,将距离设置为一个很大的数
int map[MAX_required][MAX_required];//用数组存放城市地图
int callnum[MAX_required];//该数组存放每个城市对应救援团队的数量

struct  CITY
{
	int dist; //该结点至源节点的最短距离
	bool visited;//是否被访问过
	int number;//最短路径数量,这里是为了AdvancePAT 1003那道题设置的,可以不用
	int call;//每个城市对应的救援团队数量
	int prev;//从源点到这个点的最短路径中,该点的前一个结点

}city[MAX_required];//新建数组,存放类型为CITY

void Dijkstra(int start, int end,int n)
{	
	/*int callnum[6] = { 3, 2, 1, 3, 3, 4 };
	int map[6][6] = {
		{ Max_int, 7, 9, Max_int, Max_int, 14 },
		{ 7, Max_int, 10, 15, Max_int, Max_int },
		{ 9, 10, Max_int, 11, Max_int, 2 },
		{ Max_int, 15, 11, Max_int, 6, Max_int },
		{ Max_int, Max_int, Max_int, 6, Max_int, 9 },
		{ 14, Max_int, 2, Max_int, 9, Max_int }
	};*///测试使用代码,可以忽略
	
	
	for (int i = 0; i < n; i++)//初始化所有的项
	{
		city[i].dist = Max_int;
		city[i].visited = 0;
		city[i].number = 0;
		city[i].call = 0;
		city[i].prev = 0;//这里初值是否该为0
	}

	city[start].dist = 0;//初始化源点到自己的距离为0
	city[start].number = 1;//如果不是做PAT题,该变量不需要
	city[start].call = callnum[start];//如果不是做PAT题,该变量不需要

	//求最短路径及其位置
	for (int cnt = 0; cnt < n; cnt++)//控制总共循环的次数
	{
		int Min = Max_int, pos = -1;//min记录最小路径,pos记录下一个访问结点的标记

		//找到最短距离,以及对应下标,作为下一次的起始节点
		for (int i = 0; i < n; i++)
		{
			if ((city[i].visited == 0) && (city[i].dist < Min))
			{
				Min = city[i].dist;
				pos = i;							
			}
		}

		if (pos == -1)
			break;

		city[pos].visited = 1;

		//根据下一个结点在矩阵中对应的值,调整结点到原点距离的最小值和对应的救援团队数量
		for (int j = 0; j < n; j++)
		{
			if ((city[j].visited == 0) && (map[pos][j] != Max_int))//注意这里要判断map中对应的值是否为无穷大,即没有路径
			{
				if (city[j].dist>city[pos].dist + map[pos][j])
				{
					city[j].dist = city[pos].dist + map[pos][j];
					city[j].number = city[pos].number;
					city[j].call = city[pos].call+callnum[j];
					city[j].prev = pos;
				}
				/*else if (city[j].dist==(city[pos].dist + map[pos][j]))//这种情况是为了处理最短路径有多条时的情况
				{
					city[j].number += city[pos].number;
					if (city[j].call < city[pos].call + callnum[j])
						city[j].call = city[pos].call + callnum[j];
				}*/
			}
		}
	}

	cout << "结点" << start << "到结点" << end << "的最短距离为" << city[end].dist;

	vector<int> final_path;
	final_path.push_back(end);//通过前驱结点,将end到start的最短路径找出来,放在容器中
	int temp = city[end].prev;
	while (temp != start)
	{		
		final_path.push_back(temp);
		temp = city[temp].prev;
	}	
	final_path.push_back(start);

	cout << "路径为";
	for (int i = final_path.size() - 1; i >= 0; i--)
	{
		if (i)
		{
			cout << final_path[i] << "->";
		}
		else
		{
			cout << final_path[i];
		}
	}
	cout << city[end].dist << " " << city[end].call;//这个是为了配合PAT1003那道题的,单纯的Dijkstra算法求最短路径及相应的值已经搞定
}

int main()
{
		int n, m, start, end;	//分别表示城市数量,道路数量,起始城市和终点城市
		cin >> n >> m >> start >> end;
		int i;
		for (i = 0; i<n; i++)//输入每个城市救援队数目,不做PAT请忽略这里
			cin >> callnum[i];
		int a, b, l;	
		for (int i = 0; i < n; i++)//初始化map中城市间是没有道路的
		{
			for (int j = 0; j < n; j++)
			{
				map[i][j] = Max_int;
			}
		}
		for (i = 0; i<m; i++)//输入城市间距离
		{
			cin >> a >> b >> l;
			map[a][b] = l;
			map[b][a] = l;
		}		

		//输入样例
		/*5 6 0 2
		1 2 1 5 3
		0 1 1
		0 2 2
		0 3 1
		1 2 1
		2 4 1
		3 4 1*/

		//////调试使用,可以不适用输入样例,直接用这部分调试代码。注意将int callnum[6]以后的代码写在Dijkstra函数中
		//int n = 6, m = 9;
		//int start = 0, end = 4;
		//cin >> start >> end;
		//int callnum[6] = { 3, 2, 1, 3, 3, 4 };
		//int map[6][6] = {
		//	{ Max_int, 7, 9, Max_int, Max_int, 14 },
		//	{ 7, Max_int, 10, 15, Max_int, Max_int },
		//	{ 9, 10, Max_int, 11, Max_int, 2 },
		//	{ Max_int, 15, 11, Max_int, 6, Max_int },
		//	{ Max_int, Max_int, Max_int, 6, Max_int, 9 },
		//	{ 14, Max_int, 2, Max_int, 9, Max_int }
		//};//发现这部分代码如果写在主函数里,到调用Dijkstra时,map中元素全部为0,还没太弄明白

		Dijkstra(start, end, n);

		return 0;
}





版权声明:本文为博主原创文章,未经博主允许不得转载。

彻底理解Dij算法

理解什么是dij 简单来说,就是求最短路的一种算法 理解dij的核心思想 百度给出:以起始点为中心向外层层扩展,直到扩展到终点为止 可咋理解这句话呢?层层扩展,咋扩展?什么是层? 别急,且听我...

Dijkstra+Heap+前向星存图

一切尽在代码中。。。。。。。。 /* dijkstra + heap,时间复杂度: O((n + e)log(n)). 对于稠密图来说,仍然是dij+heap快,而且越稠密越快!...

Dij.......最短路径算法

#ifndef _ALGRAPH_H #define _ALGRAPH_H #include // #include "Queue.h" /* * 邻接表 存储 图 */ #defin...

Dijkstra算法与实现--进阶篇

1. 本文主要集中使用最小堆

从零开始学递归与分治

递归的定义: 程序调用自身的编程技巧称为递归。递归做为一种算法在程序设计语言中广泛应用。 一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题...

从零开始学动态规划

本文在写作过程中参考了大量资料,不能一一列举,还请见谅。 动态规划的定义: 动态规划是运筹学的一个分支,是求解决策过程的最优化的数学方法。20世纪50年代初美国数学家R.E.Bellman等人在研究多...

二分图及其匹配算法——最大匹配数(最小覆盖数)、最大独立数、最小路径覆盖、带权最优匹配

§1图论点、边集和二分图的相关概念和性质 §2二分图最大匹配求解 匈牙利算法、Hopcroft-Karp算法 §3二分图最小覆盖集和最大独立集的构造 §4二分图最小路径覆盖求解...
  • tham_
  • tham_
  • 2017年06月05日 22:41
  • 634

最优路径算法

  • 2012年09月27日 11:00
  • 40KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Dijastra最优路径算法
举报原因:
原因补充:

(最多只允许输入30个字)