dijkstra算法及两点路径算法

本文分享了一个基于Dijkstra算法实现的最短路径搜索程序,并详细展示了算法的具体实现过程。此外,还介绍了一种遍历算法来寻找所有可能的路径。

昨天看到某人写的最短路径搜索,遂把前两年写的dijkstra算法及两点路径算法拿出来show一下。

参考/* see http://www.5do8.com/blog/doc/596/index.aspx */

 

source code下载: http://download.youkuaiyun.com/source/2253213

备注:这个程序是我学EXCEL的时候顺手写的,刚才看代码,差点儿没看懂,典型的C型C++程序,汗一下。

 

 

/*
 * dijkstra算法
 */
void build_node_dij(CNodeList *pNode,   // 输入的节点图
     CLinkList *pLink,   // 输入的节点之间的连接
     int     iStartNode,  // 起始节点号
     CLinkList *pShortLink  // 输出的最短路径
     )
{
 CNodeList m_remain;   // 剩下的NODE
 CNodeList m_selected;  // 已经选择的node
 ST_NODE *pn,*pn2;
 ST_LINK *pl;
 ST_LINK m_lnk;
 char m_sSearchBuf[20];
 m_remain.CopyFromList(pNode);  // 1. 从输入的原始数据进行复制
 m_selected.Empty();     // 2. 清空已经选择过的节点
 pShortLink->Empty();
 
 pn = m_remain.FindNode(iStartNode); // 3. 首先选择开始节点
 if (pn == NULL)
 {
  printf("Can not find start node:%d/n",iStartNode);
  return;
 }
 pn->m_iDistance = 0;
L_NEXTLOOP:
 // 4. 把节点摘除,添加到已经选择的节点中
 m_selected.AddNode(pn);
 m_remain.RemoveNode(pn);
 // 5. 在剩下的节点表中,更新与这个节点相关的距离
 ZeroMemory(m_sSearchBuf,sizeof(m_sSearchBuf));
 pl = pLink->FindNextLink(TRUE,pn->m_iNode,m_sSearchBuf);// 首先查找以这个节点开始的link段
 while (pl)
 {
  pn2=m_remain.FindNode(pl->m_iDest);     // 看看link的目标是否在remain里
  if (pn2)           // 如果在remain里,则需要更新距离
  {
   if (pn2->m_iDistance <0)
    pn2->m_iDistance = pn->m_iDistance + pl->m_iDistance;
   else
   {
    if (pn2->m_iDistance> pn->m_iDistance+pl->m_iDistance)
     pn2->m_iDistance = pn->m_iDistance+pl->m_iDistance;
   }
  }
  pl = pLink->FindNextLink(TRUE,pn->m_iNode,m_sSearchBuf); 
 }
 // 6. 在剩下的节点表中,选择下一个到达的节点
 //   这个节点应当是最短距离的
 pn = m_remain.FindShortestNode();
 if (pn == NULL)   // 如果已经没有了,则表示已经遍历完成了(或者存在孤岛)
 {
  printf("----------------------------------------------/n");
  printf("dump selected nodes:/n");
  m_selected.dump();
  printf("----------------------------------------------/n");
  printf("dump remain nodes:/n");
  m_remain.dump();
  return;
 }
 pn2 = NULL;
 // 7. 从已经选择的节点中,找到到这个节点的最短距离
 ZeroMemory(m_sSearchBuf,sizeof(m_sSearchBuf));
 pl = pLink->FindNextLink(FALSE,pn->m_iNode,m_sSearchBuf);// 首先查找以这个节点结束的link段
 while(pl)
 {
  pn2 = m_selected.FindNode(pl->m_iFrom);  // 看看开始节点是否在已经select里
  if (pn2)
  {
   /* 如果发现这个已经选择过的节点就是到这个尚未选择的节点的最短节点 */
   /* 那么就是他了 */
   if (pn2->m_iDistance + pl->m_iDistance == pn->m_iDistance)
   {
    m_lnk.m_iFrom = pn2->m_iNode; // 从已经选择的节点开始
    m_lnk.m_iDest = pn->m_iNode; // 到尚未选择的节点终止
    m_lnk.m_iDistance = pl->m_iDistance; // 设定好距离
    pShortLink->AddLink(&m_lnk);
    goto L_NEXTLOOP;
   }
  }
  pl = pLink->FindNextLink(FALSE,pn->m_iNode,m_sSearchBuf);// 首先查找以这个节点结束的link段
 }
 // 没有?不可能啊
 printf("Fatal Error:Can't find shortest selected node to dest node:%d/n",pn->m_iNode);
 printf("----------------------------------------------/n");
 printf("dump selected node:/n");
 m_selected.dump();
 printf("----------------------------------------------/n");
 printf("dump remain node:/n");
 m_remain.dump();
 printf("----------------------------------------------/n");
 printf("dump links:/n");
 pShortLink->dump();
}
/*
 * 遍历算法
 */
void build_all_path(CNodeList * pNode,   // 输入节点表
     CLinkList * pLink,   // 连接表
     int   iOrgFrom,  // 原始开始节点
     int   iFrom,   // 开始节点
     int   iDest,   // 终止节点
     CLinkList * pWalkPath,  // 当前走到的路径
     CPathList * pPath   // 输出的path表
     )
{
 ST_PATH m_path;
 CNodeList m_node;
 ST_NODE *pn,*pn2;
 ST_LINK *pl;
 CLinkList m_Walk;
 char m_sSearchBuf[20];
 if (iFrom == iDest)       // 已经遍历到了,那么就记录下这个路径返回吧
 {
  ZeroMemory(&m_path,sizeof(m_path));
  m_path.m_iFrom = iOrgFrom;
  m_path.m_iDest = iDest;
  m_path.m_pLink = pWalkPath;
  pPath->AddPath(&m_path);
  return;
 }
 // 1. 复制这个nodelist
 // 2. 从这个nodlist中删除这个开始的节点
 m_node.CopyFromList(pNode);
 m_Walk.CopyFromList(pWalkPath);
 pn = m_node.FindNode(iFrom);
 if (pn == NULL)
 {
  printf("Internal Error: can't find source node:%d/n",iFrom);
  return;
 }
 m_node.RemoveNode(pn);
 // 3. 依次找从这个节点开始的连接
 ZeroMemory(m_sSearchBuf,sizeof(m_sSearchBuf));
 pl = pLink->FindNextLink(TRUE,iFrom,m_sSearchBuf);// 首先查找以这个节点开始的link段
 while (pl)
 {
  pn2=m_node.FindNode(pl->m_iDest);  // 看看link的目标是否在剩下的节点里
  if (pn2)        // 如果在剩下的节点里,那么就开始递归
  {
   m_Walk.AddLink(pl);     // 路径增加一个到这里的路径
   build_all_path(&m_node,pLink,iOrgFrom,pl->m_iDest,iDest,&m_Walk,pPath);
   m_Walk.RemoveLink(pl);
  }
  pl = pLink->FindNextLink(TRUE,iFrom,m_sSearchBuf); 
 }
 return;
}
int main(int argc, char* argv[])
{
 CNodeList m_node;
 CLinkList m_link;
 CLinkList m_slink;
 CLinkList m_dummy;
 CPathList m_path;
 int i;
 build_org_node(&m_node);
 build_org_link(&m_link);
#if 0
 printf("Building shortest link/n");
 for(i=0;i<9;i++)
 {
  build_node_dij(&m_node,&m_link,i,&m_slink);
  printf("----------------------------------------------/n");
  printf("dump links: from %d/n",i);
  m_slink.dump();
 }
#endif
 build_all_path(&m_node,&m_link,0,0,8,&m_dummy,&m_path);
 m_path.dump();
 return 0;
}
 

 

 

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值