关闭

Dijastra最优路径算法

标签: 算法导论数据结构算法C++
698人阅读 评论(0) 收藏 举报
分类:

关于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;
}





0
0

猜你在找
【直播】机器学习&数据挖掘7周实训--韦玮
【套餐】系统集成项目管理工程师顺利通关--徐朋
【直播】3小时掌握Docker最佳实战-徐西宁
【套餐】机器学习系列套餐(算法+实战)--唐宇迪
【直播】计算机视觉原理及实战--屈教授
【套餐】微信订阅号+服务号Java版 v2.0--翟东平
【直播】机器学习之矩阵--黄博士
【套餐】微信订阅号+服务号Java版 v2.0--翟东平
【直播】机器学习之凸优化--马博士
【套餐】Javascript 设计模式实战--曾亮
查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:52849次
    • 积分:1392
    • 等级:
    • 排名:千里之外
    • 原创:77篇
    • 转载:84篇
    • 译文:0篇
    • 评论:4条
    最新评论