最短路是个老问题了,大神们留下很多文档但是很多都是针对算法使用一些固定大小的数组进行数据存储在实际应用中受到限制,这里自己练习一下,主要用了一些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++ 最短路两种算法的更多相关文章

  1. 最小生成树算法 prim kruskal两种算法实现 HDU-1863 畅通工程

    最小生成树 通俗解释:一个连通图,可将这个连通图删减任意条边,仍然保持连通图的状态并且所有边权值加起来的总和使其达到最小.这就是最小生成树 可以参考下图,便于理解 原来的图: 最小生成树(蓝色线): ...

  2. 图文详解两种算法:深度优先遍历(DFS)和广度优先遍历(BFS)

    参考网址:图文详解两种算法:深度优先遍历(DFS)和广度优先遍历(BFS) - 51CTO.COM 深度优先遍历(Depth First Search, 简称 DFS) 与广度优先遍历(Breath ...

  3. 「每日五分钟,玩转JVM」:两种算法

    前言 上篇文章,我们了解了GC 的相关概念,这篇文章我们通过两个算法来了解如何去确定堆中的对象实例哪些是我们需要去回收的垃圾对象. 引用计数算法 引用计数法的原理很简单,就是在对象中维护一个计数器,当 ...

  4. HDU 1160 排序或者通过最短路两种方法解决

    题目大意: 给定一堆点,具有x,y两个值 找到一组最多的序列,保证点由前到后,x严格上升,y严格下降,并把最大的数目和这一组根据点的编号输出来 这里用两种方法来求解: 1. 我们可以一开始就将数组根据 ...

  5. 求最大公约数(GCD)的两种算法

    之前一直只知道欧几里得辗转相除法,今天学习了一下另外一种.在处理大数时更优秀的算法--Stein 特此记载 1.欧几里得(Euclid)算法 又称辗转相除法,依据定理gcd(a,b)=gcd(b,a% ...

  6. 求逆序对常用的两种算法 ----归并排 & 树状数组

    网上看了一些归并排求逆序对的文章,又看了一些树状数组的,觉得自己也写一篇试试看吧,然后本文大体也就讲个思路(没有例题),但是还是会有个程序框架的 好了下面是正文 归并排求逆序对 树状数组求逆序对 一. ...

  7. 一句话比较两种算法的优越性[蓝桥杯,LeetCode]

    动态规划 166 数学 155 字符串 146 树 120 哈希表 119 深度优先搜索 109 二分查找 79 贪心算法 64 双指针 59 广度优先搜索 54 栈 53 回溯算法 49 设计 41 ...

  8. 利用深搜和宽搜两种算法解决TreeView控件加载文件的问题。

    利用TreeView控件加载文件,必须遍历处所有的文件和文件夹. 深搜算法用到了递归. using System; using System.Collections.Generic; using Sy ...

  9. Leetcode94. Binary Tree Inorder Traversal二叉树的中序遍历(两种算法)

    给定一个二叉树,返回它的中序 遍历. 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [1,3,2] 进阶: 递归算法很简单,你可以通过迭代算法完成吗? 递归: class So ...

随机推荐

  1. 【Heritrix基础教程之1】在Eclipse中配置Heritrix

    一.新建项目并将Heritrix源代码导入 1.下载heritrix-1.14.4-src.zip和heritrix-1.14.4.zip两个压缩包,并解压,以后分别简称SRC包和ZIP包: 2.在E ...

  2. Ubuntu16.04/windows7修改本地hosts文件

    1. 从github上下载最新的hosts文件:https://serve.netsh.org/pub/ipv4-hosts/ ubuntu16.04: 第二步:Ctrl+Alt+T 打开ubuntu ...

  3. struts----通配符设置

    本次学习的内容是struts通配符配置: 具体内容为: 一.准备工作 1.新建Web工程 2.添加struts:右键点击工程名选择My Eclipse-->点击add struts..--> ...

  4. Vim常见快捷键汇总

    编辑命令: i 词前插入 a 词后插入 I 行首插入 A 行尾插入 o 新建一行编辑 O 在上面新建一行 插入: 10 i * [ESC] 插入10个* 25 a xx [ESC] 插入25个xx J ...

  5. Bind开启IPv6功能

    [root@localhost sbin]# ./named -v bind 9.5.1-p3-v3.0.9 1,服务器开启IPv6服务 网卡配置v6地址 [root@localhost ~]# if ...

  6. 单台电脑上启动多个Modelsim图形环境窗口的简单办法(windows)

    1 单台电脑上启动多个Modelsim图形环境窗口的简单办法(windows) http://blog.21ic.com/user1/3128/archives/2010/73447.html   单 ...

  7. RabbitMQ 原文译06--Remote procedure call(RPC)

    在第三篇文章中, 我们学习了怎么使用队列在多了消息消费者当中进行耗时任务轮询. 但是如果我们想要在远程电脑上运行一个方法,然后等待其执行结果,这就是一个不同的场景,这种就是我们一般讲的RPC(远程过程 ...

  8. CA 配置网站映射

     

  9. 关于MD5校验和java工程下的校验

    File file = new File("cos_code2003.bin"); System.out.println(file.length()); byte[] data = ...

  10. php中怎么实现后台执行?

    http://www.cnblogs.com/zdz8207/p/3765567.html php中实现后台执行的方法: ignore_user_abort(true); // 后台运行set_tim ...