c++ 最短路两种算法
最短路是个老问题了,大神们留下很多文档但是很多都是针对算法使用一些固定大小的数组进行数据存储在实际应用中受到限制,这里自己练习一下,主要用了一些c++的stl,减少了固定长度数组的依赖,换一种写法试图提高可读性。有兴趣的同学可以试着将map/set 换成 hash_set/hash_map 应该能获得更高的效率,对于稀疏表,内存还是能省不少的。
参考文献: http://www.cnblogs.com/hxsyl/p/3270401.html
1 /************************************************************************/
2 /* 尽量用简单快速好理解的方法完成图的最短路径 */
3 /************************************************************************/
4 #include <stdio.h>
5 #include <string.h>
6 #include <malloc.h>
7
8 #include <iostream>
9 #include <sstream>
10 #include <string>
11
12 #include <set>
13 #include <map>
14 #include <vector>
15 #include <queue>
16
17 #include <algorithm>
18
19 using namespace std;
20
21 typedef size_t Index;
22
23 // 使用整数比string快
24 map<string, Index> g_mapNode; // string -> index
25 map<Index, string> g_mapNodeIndex; // index -> string
26 map<Index, set<Index> > g_mapLink; // 邻接表
27
28 inline bool IsNullString(const char* pcName)
29 {
30 return (NULL == pcName) && ('\0' == pcName[]);
31 }
32
33 inline bool IsNodeExist(const string& strName)
34 {
35 return g_mapNode.end() != g_mapNode.find(strName);
36 }
37
38 bool FindPath1(Index uSource, Index uTarget, vector<Index>& vecRlst)
39 {
40 map<Index, size_t> mapDistence;
41 map<Index, Index> mapPath;
42
43 // inistalize
44 map<Index, set<Index> >::iterator iterInit = g_mapLink.begin();
45 for (; iterInit != g_mapLink.end(); ++iterInit)
46 {
47 if (iterInit->second.count(uTarget) != )
48 {
49 mapDistence[iterInit->first] = ;
50 mapPath[iterInit->first] = uTarget;
51 }
52 }
53
54 // find
55 size_t uNodeNum = g_mapNode.size();
56 for (size_t i = ; i < uNodeNum; ++i)
57 {
58 for (size_t j = ; j < uNodeNum; ++j)
59 {
60 if (g_mapLink.count(i) != && g_mapLink[i].count(j) != ) // i - > j 是通的
61 {
62 if (mapDistence.count(j) != // j -> uTarget是通的
63 && (mapDistence.count(i) == // i -> uTarget 不存在或者 比从 j走远
64 || (mapDistence[j] + < mapDistence[i])))
65 {
66 mapDistence[i] = mapDistence[j] + ; // 更新距离
67 mapPath[i] = j; // 更新下一跳地址
68 }
69 }
70 }
71 }
72
73 // 不可到达
74 if (mapDistence.count(uSource) == )
75 {
76 return false;
77 }
78
79 while (uSource != uTarget)
80 {
81 vecRlst.push_back(uSource);
82 uSource = mapPath[uSource];
83 }
84 vecRlst.push_back(uSource);
85
86 return true;
87 }
88
89 bool FindPath2(Index uSource, Index uTarget, vector<Index>& vecRlst)
90 {
91 map<Index, Index> mapLastJump;
92 queue<Index> queNodeQue;
93
94 bool bIsFind = false;
95 queNodeQue.push(uSource);
96 while (!queNodeQue.empty() && !bIsFind)
97 {
98 Index uIdx = queNodeQue.front();
99 queNodeQue.pop();
if (g_mapLink.count(uIdx) == )
{
continue;
}
set<Index>::iterator iter = g_mapLink[uIdx].begin();
for (; iter != g_mapLink[uIdx].end(); iter++)
{
if (mapLastJump.count(*iter) != )
{
continue;
}
mapLastJump[*iter] = uIdx;
if (*iter == uTarget)
{
bIsFind = true;
break;
}
queNodeQue.push(*iter);
}
}
if (!bIsFind)
{
return false;
}
while(uTarget != uSource)
{
vecRlst.push_back(uTarget);
uTarget = mapLastJump[uTarget];
}
vecRlst.push_back(uSource);
reverse(vecRlst.begin(), vecRlst.end());
return true;
}
void cmdInitialize()
{
g_mapNode.clear();
g_mapLink.clear();
}
bool cmdAddNode(const char *pcNode)
{
if (IsNullString(pcNode))
{
return false;
}
string strName(pcNode);
if (IsNodeExist(strName))
{
return false;
}
Index uIndex = g_mapNode.size();
g_mapNode[strName] = uIndex;
g_mapNodeIndex[uIndex] = strName;
return true;
}
bool cmdAddLink(const char *pcSource, const char *pcTarget)
{
if (IsNullString(pcSource) || IsNullString(pcTarget))
{
return false;
}
string strSource(pcSource);
string strTarget(pcTarget);
if (!IsNodeExist(strSource) || !IsNodeExist(strTarget) || strSource == strTarget)
{
return false;
}
g_mapLink[g_mapNode[strSource]].insert(g_mapNode[strTarget]);
g_mapLink[g_mapNode[strTarget]].insert(g_mapNode[strSource]);
return true;
}
bool cmdFindPath(const char *pcSource, const char *pcTarget, char **ppcRlstPath)
{
if (NULL == ppcRlstPath)
{
return false;
}
*ppcRlstPath = NULL;
string strSource(pcSource);
string strTarget(pcTarget);
if (!IsNodeExist(strSource) || !IsNodeExist(strTarget) || strSource == strTarget)
{
return false;
}
vector<Index> vecPath;
//if(!FindPath1(g_mapNode[strSource], g_mapNode[strTarget], vecPath))
if(!FindPath2(g_mapNode[strSource], g_mapNode[strTarget], vecPath))
{
return false;
}
string strOutPut;
stringstream ssOutPut("");
for (size_t u = ; u < vecPath.size(); ++u)
{
ssOutPut << g_mapNodeIndex[vecPath[u]] << "->";
}
strOutPut = ssOutPut.str();
strOutPut = strOutPut.substr(, strOutPut.length() - );
*ppcRlstPath = (char *)malloc(sizeof(char) * (strOutPut.length() + ));
if (NULL == *ppcRlstPath)
{
return false;
}
strcpy(*ppcRlstPath, strOutPut.c_str());
return true;
}
int main()
{
cmdInitialize();
cmdAddNode("A");
cmdAddNode("B");
cmdAddNode("C");
cmdAddNode("D");
cmdAddLink("A", "B");
cmdAddLink("B", "C");
cmdAddLink("C", "D");
cmdAddLink("B", "D");
char *pcPath = NULL;
if (cmdFindPath("A", "D", &pcPath))
{
printf("%s\n", pcPath);
free(pcPath);
pcPath = NULL;
}
return ;
254 }
c++ 最短路两种算法的更多相关文章
- 最小生成树算法 prim kruskal两种算法实现 HDU-1863 畅通工程
最小生成树 通俗解释:一个连通图,可将这个连通图删减任意条边,仍然保持连通图的状态并且所有边权值加起来的总和使其达到最小.这就是最小生成树 可以参考下图,便于理解 原来的图: 最小生成树(蓝色线): ...
- 图文详解两种算法:深度优先遍历(DFS)和广度优先遍历(BFS)
参考网址:图文详解两种算法:深度优先遍历(DFS)和广度优先遍历(BFS) - 51CTO.COM 深度优先遍历(Depth First Search, 简称 DFS) 与广度优先遍历(Breath ...
- 「每日五分钟,玩转JVM」:两种算法
前言 上篇文章,我们了解了GC 的相关概念,这篇文章我们通过两个算法来了解如何去确定堆中的对象实例哪些是我们需要去回收的垃圾对象. 引用计数算法 引用计数法的原理很简单,就是在对象中维护一个计数器,当 ...
- HDU 1160 排序或者通过最短路两种方法解决
题目大意: 给定一堆点,具有x,y两个值 找到一组最多的序列,保证点由前到后,x严格上升,y严格下降,并把最大的数目和这一组根据点的编号输出来 这里用两种方法来求解: 1. 我们可以一开始就将数组根据 ...
- 求最大公约数(GCD)的两种算法
之前一直只知道欧几里得辗转相除法,今天学习了一下另外一种.在处理大数时更优秀的算法--Stein 特此记载 1.欧几里得(Euclid)算法 又称辗转相除法,依据定理gcd(a,b)=gcd(b,a% ...
- 求逆序对常用的两种算法 ----归并排 & 树状数组
网上看了一些归并排求逆序对的文章,又看了一些树状数组的,觉得自己也写一篇试试看吧,然后本文大体也就讲个思路(没有例题),但是还是会有个程序框架的 好了下面是正文 归并排求逆序对 树状数组求逆序对 一. ...
- 一句话比较两种算法的优越性[蓝桥杯,LeetCode]
动态规划 166 数学 155 字符串 146 树 120 哈希表 119 深度优先搜索 109 二分查找 79 贪心算法 64 双指针 59 广度优先搜索 54 栈 53 回溯算法 49 设计 41 ...
- 利用深搜和宽搜两种算法解决TreeView控件加载文件的问题。
利用TreeView控件加载文件,必须遍历处所有的文件和文件夹. 深搜算法用到了递归. using System; using System.Collections.Generic; using Sy ...
- Leetcode94. Binary Tree Inorder Traversal二叉树的中序遍历(两种算法)
给定一个二叉树,返回它的中序 遍历. 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [1,3,2] 进阶: 递归算法很简单,你可以通过迭代算法完成吗? 递归: class So ...
随机推荐
- ubuntu12.04的vim配置
ubuntu12.04中使用的vim的版本不支持像语法高亮和文件类型检测等配置 #sudo apt-get install vim vim默认的配置使用起来还不能让人满意,还需要自己配置默认配置文件是 ...
- GitHub干货分享(APP引导页的高度集成 - DHGuidePageHUD)
每一个APP都会用到APP引导页,分量不重但是不可缺少,不论是APP的首次安装还是版本的更新,首先展现给用户眼前的也就只有它了,当然这里讲的不是APP引导页的美化而是APP引导页的高度集成,一行代码搞 ...
- C#知识总结
Control类属于Sytem的命名空间 表示控制台标准的输入输出和错误流提供用于从控制台读取单个字符或正行的方法还提供了很多写入的的方法, static 关键字是对方法的修饰 二 数据类型的分类 数 ...
- sqlServer 求当前周的第一天和最后一天,当前月的第一天和最后一天,前三个月的第一天和今天
---当前周的第一天 ),DATEADD(day,-(DATEPART(weekday,GETDATE())-),GETDATE()) , )as'周一', CONVERT(varchar(),DAT ...
- ACM——A + B Problem (1)
A + B Problem (1) 时间限制(普通/Java):1000MS/3000MS 运行内存限制:65536KByte总提交:5907 测试通过:151 ...
- iOS 动画基础
原文:http://www.cnblogs.com/lujianwenance/p/5733846.html 今天说一下有关动画的基础,希望能帮助到一些刚接触iOS动画或者刚开始学习iOS的同学, ...
- C语言——N个人围成一圈报数淘汰问题
<一>问题描述: 有17个人围成一圈(编号为0-16),从第 0号的人开始从 1报数, 凡报到 3的倍数的人离开圈子,然后再数下去,直到最后只剩下一个人为止. 问此人原来的位置是多少号? ...
- Invalid SOAP message or SOAP version mismatch
在把过车数据上传到海康平台的时候返回: Invalid SOAP message or SOAP version mismatch 网上找了说是协议问题,但是不知道如何解决: 我用客户端是c#2.0; ...
- Nuage SDN
Nuage推出纯软件解决方案虚拟化业务平台(VSP)由三部分组成:虚拟化业务目录(VSD).虚拟化业务控制器(VSC)和虚拟路由与交换(VRS). VSD是业务/IT策略引擎,可提供业务模板与分析,每 ...
- 九度OJ 1202 排序 -- 堆排序
题目地址:http://ac.jobdu.com/problem.php?pid=1202 题目描述: 对输入的n个数进行排序并输出. 输入: 输入的第一行包括一个整数n(1<=n<=10 ...