核心思想是从已知的最短路径推算未知的最短路径。

添加程序:

 #ifndef GRAPH_H
#define GRAPH_H #include "Object.h"
#include "SharedPointer.h"
#include "Array.h"
#include "DynamicArray.h"
#include "LinkQueue.h"
#include "LinkStack.h"
#include "Sort.h" namespace DTLib
{ template < typename E >
struct Edge : public Object
{
int b;
int e;
E data; Edge(int i=-, int j=-)
{
b = i;
e = j;
} Edge(int i, int j, const E& value)
{
b = i;
e = j;
data = value;
} bool operator == (const Edge<E>& obj)
{
return (b == obj.b) && (e == obj.e); //在这里不关注权值大小
} bool operator != (const Edge<E>& obj)
{
return !(*this == obj);
} bool operator < (const Edge<E>& obj)
{
return (data < obj.data);
} bool operator > (const Edge<E>& obj)
{
return (data > obj.data);
}
}; template < typename V, typename E >
class Graph : public Object
{
protected:
template < typename T >
DynamicArray<T>* toArray(LinkQueue<T>& queue)
{
DynamicArray<T>* ret = new DynamicArray<T>(queue.length()); if( ret != NULL )
{
for(int i=; i<ret->length(); i++, queue.remove())
{
ret->set(i, queue.front());
}
}
else
{
THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create ret object...");
} return ret;
} SharedPointer< Array<Edge<E> > > getUndirectedEdges()
{
DynamicArray<Edge<E>>* ret = NULL; if( asUndirected() )
{
LinkQueue<Edge<E>> queue; for(int i=; i<vCount(); i++)
{
for(int j=i; j<vCount(); j++)
{
if( isAdjacent(i, j) )
{
queue.add(Edge<E>(i, j, getEdge(i, j)));
}
}
} ret = toArray(queue);
}
else
{
THROW_EXCEPTION(InvalidOperationException, "This function is for undirected graph only...");
} return ret;
} int find(Array<int>& p, int v)
{
while( p[v] != -)
{
v = p[v];
} return v;
}
public:
virtual V getVertex(int i) = ;
virtual bool getVertex(int i, V& value) = ;
virtual bool setVertex(int i, const V& value) = ;
virtual SharedPointer< Array<int> > getAdjacent(int i) = ;
virtual bool isAdjacent(int i, int j) = ;
virtual E getEdge(int i, int j) = ;
virtual bool getEdge(int i, int j, E& value) = ;
virtual bool setEdge(int i, int j, const E& value) = ;
virtual bool removeEdge(int i, int j) = ;
virtual int vCount() = ;
virtual int eCount() = ;
virtual int OD(int i) = ;
virtual int ID(int i) = ; virtual int TD(int i)
{
return ID(i) + OD(i);
} bool asUndirected()
{
bool ret = true; for(int i=; i<vCount(); i++)
{
for(int j=; j<vCount(); j++)
{
if( isAdjacent(i, j) )
{
ret = ret && isAdjacent(j, i) && (getEdge(i, j) == getEdge(j, i));
}
}
} return ret;
} SharedPointer< Array< Edge<E > > > prim(const E& LIMIT, const bool MINIUM = true) //参数为理论上的最大权值
{
LinkQueue< Edge<E> > ret; if( asUndirected() )
{
DynamicArray<int> adjVex(vCount());
DynamicArray<bool> mark(vCount());
DynamicArray<E> cost(vCount());
SharedPointer< Array<int> > aj = NULL;
bool end = false;
int v = ; for(int i=; i<vCount(); i++)
{
adjVex[i] = -;
mark[i] = false;
cost[i] = LIMIT;
} mark[v] = true; aj = getAdjacent(v); for(int j=; j<aj->length(); j++)
{
cost[(*aj)[j]] = getEdge(v, (*aj)[j]);
adjVex[(*aj)[j]] = v;
} for(int i=; (i<vCount()) && !end; i++)
{
E m = LIMIT;
int k = -; for(int j=; j<vCount(); j++)
{
if( !mark[j] && (MINIUM ? (cost[j] < m) : (cost[j] > m)))
{
m = cost[j];
k = j;
}
} end = (k == -); if( !end )
{
ret.add(Edge<E>(adjVex[k], k, getEdge(adjVex[k], k))); mark[k] = true; aj = getAdjacent(k); for(int j=; j<aj->length(); j++)
{
if( !mark[(*aj)[j]] && (MINIUM ? (getEdge(k, (*aj)[j]) < cost[(*aj)[j]]) : (getEdge(k, (*aj)[j]) > cost[(*aj)[j]])) )
{
cost[(*aj)[j]] = getEdge(k, (*aj)[j]);
adjVex[(*aj)[j]] = k;
}
}
}
}
}
else
{
THROW_EXCEPTION(InvalidOperationException, "Prim operator is for undirected graph only...");
} if( ret.length() != (vCount() - ) )
{
THROW_EXCEPTION(InvalidOperationException, "No enough edge for prim operation...");
} return toArray(ret);
} SharedPointer< Array<Edge<E> > > kruskal(const bool MINMUM = true)
{
LinkQueue< Edge<E> > ret; SharedPointer< Array< Edge<E> > > edges = getUndirectedEdges(); DynamicArray<int> p(vCount()); //前驱标记数组 for(int i=; i<p.length(); i++)
{
p[i] = -;
} Sort::Shell(*edges, MINMUM); for(int i=; (i<edges->length()) && (ret.length() < (vCount() - )); i++)
{
int b = find(p, (*edges)[i].b);
int e = find(p, (*edges)[i].e); if( b != e )
{
p[e] = b; ret.add((*edges)[i]);
}
} if( ret.length() != (vCount() - ) )
{
THROW_EXCEPTION(InvalidOperationException, "No enough edges for Kruskal operation...");
} return toArray(ret);
} SharedPointer< Array<int> > BFS(int i)
{
DynamicArray<int>* ret = NULL; if( ( <= i) && (i < vCount()) )
{
LinkQueue<int> q;
LinkQueue<int> r;
DynamicArray<bool> visited(vCount()); for(int i=; i<visited.length(); i++)
{
visited[i] = false;
} q.add(i); while( q.length() > )
{
int v = q.front(); q.remove(); if( !visited[v] )
{
SharedPointer< Array<int> > aj = getAdjacent(v); for(int j=; j<aj->length(); j++)
{
q.add((*aj)[j]);
} r.add(v); visited[v] = true;
}
} ret = toArray(r);
}
else
{
THROW_EXCEPTION(InvalidParameterException, "Index i is invalid...");
} return ret;
} SharedPointer< Array<int> > DFS(int i)
{
DynamicArray<int>* ret = NULL; if( ( <= i) && (i < vCount()) )
{
LinkStack<int> s;
LinkQueue<int> r;
DynamicArray<bool> visited(vCount()); for(int j=; j<visited.length(); j++)
{
visited[j] = false;
} s.push(i); while( s.size() > )
{
int v = s.top(); s.pop(); if( !visited[v] )
{
SharedPointer< Array<int> > aj = getAdjacent(v); for(int j=aj->length() - ; j>=; j--)
{
s.push((*aj)[j]);
} r.add(v); visited[v] = true;
}
} ret = toArray(r);
}
else
{
THROW_EXCEPTION(InvalidParameterException, "Index i is invalid...");
} return ret;
} SharedPointer<Array<int>> dijkstra(int i, int j, const E& LIMIT)
{
LinkQueue<int> ret; if( ( <= i) && (i < vCount()) && ( <= j) && (j < vCount()) )
{
DynamicArray<E> dist(vCount());
DynamicArray<int> path(vCount());
DynamicArray<bool> mark(vCount()); for(int k=; k<vCount(); k++)
{
mark[k] = false;
path[k] = -; dist[k] = isAdjacent(i, k) ? (path[k] = i, getEdge(i, k)) : LIMIT;
} mark[i] = true; for(int k=; k<vCount(); k++)
{
E m = LIMIT;
int u = -; for(int w=; w<vCount(); w++)
{
if( !mark[w] && (dist[w] < m) )
{
m = dist[w];
u = w;
}
} if( u == - )
{
break;
} mark[u] = true; for(int w=; w<vCount(); w++)
{
if( !mark[w] && isAdjacent(u, w) && (dist[u] + getEdge(u, w) < dist[w]) )
{
dist[w] = dist[u] + getEdge(u, w);
path[w] = u;
}
}
} LinkStack<int> s; s.push(j); for(int k=path[j]; k != -; k=path[k])
{
s.push(k);
} while( s.size() > )
{
ret.add(s.top()); s.pop();
}
}
else
{
THROW_EXCEPTION(InvalidParameterException, "Index<i, j> is invalid...");
} if( ret.length() < )
{
THROW_EXCEPTION(ArithmeticException, "There is no path grom i to j...");
} return toArray(ret);
}
}; } #endif // GRAPH_H

测试程序如下:

 #include <iostream>
#include "MatrixGraph.h"
#include "ListGraph.h" using namespace std;
using namespace DTLib; template< typename V, typename E >
Graph<V, E>& GraphEasy()
{
static MatrixGraph<, V, E> g; g.setEdge(, , );
g.setEdge(, , );
g.setEdge(, , );
g.setEdge(, , );
g.setEdge(, , ); return g;
} template< typename V, typename E >
Graph<V, E>& GraphComplex()
{
static ListGraph<V, E> g(); g.setEdge(, , );
g.setEdge(, , );
g.setEdge(, , ); g.setEdge(, , ); g.setEdge(, , ); g.setEdge(, , );
g.setEdge(, , ); return g;
} int main()
{
Graph<int, int>& g = GraphComplex<int, int>();
SharedPointer< Array<int> > p = g.dijkstra(, , ); for(int i=; i<p->length(); i++)
{
cout << (*p)[i] << " ";
} cout << endl; return ;
}

结果如下:

小结:

第七十八课 最短路径(Dijkstra)的更多相关文章

  1. 第七十九课 最短路径(Floyd)

    程序如下: #ifndef GRAPH_H #define GRAPH_H #include "Object.h" #include "SharedPointer.h&q ...

  2. NeHe OpenGL教程 第十八课:二次几何体

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  3. NeHe OpenGL教程 第四十八课:轨迹球

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  4. NeHe OpenGL教程 第三十八课:资源文件

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  5. NeHe OpenGL教程 第二十八课:贝塞尔曲面

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  6. Unity3D研究院之Jenkins的使用(七十八)

    长夜漫漫无心睡眠,来一篇嘿嘿.我相信如果已经用Shell脚本完成IOS和Android打包的朋友一定需要Jenkins 怎么才能让策划打包ipa和apk?怎么才能彻底省去程序的时间,只要在同一局域网内 ...

  7. (七十八)使用第三方框架INTULocationManager实现定位

    前面(第七十五.七十六篇)讲述了如何通过CoreLocation获取位置,授权.获取等相当复杂,如果借助于第三方框架,可以简单的实现授权与定位. 首先在GitHub中搜索LocationManager ...

  8. 深入浅出CChart 每日一课——第十八课 女神的套娃,玩转对话框

    前面笨笨已经给大家展示了CChart编程的N个例子.这些例子中,我们的CChart图像都是绘制在程序的主窗口中的. 在很多情况下,我们面对的情形不是这样的.这节课笨笨就给大家介绍一下怎样在对话框中用C ...

  9. 《手把手教你》系列基础篇(七十八)-java+ selenium自动化测试-框架设计基础-TestNG依赖测试- 中篇(详解教程)

    1.简介 上一篇讲解了依赖测试的各种方法,今天继续讲解依赖测试的方法,这一篇主要是讲解和分享通过xml文件配置组名依赖方法( 主要是测试组的用法).废话不说,直接上干货. 2.实例 测试组:一个组可包 ...

随机推荐

  1. 配置firewalld端口转发

    题:在系统 system1 设定端口转发,要求: 1.在172.24.8.0/24网络中的系统,访问system1的本地端口 5423 将被转发到 80 2.此设置必须永久有效 答: # 配置转发端口 ...

  2. CSS 标签选择器

    CSS 标签选择器 再<stype>标签内,通过指定输入标签来配置CSS样式 <html> <head> <!-- style 设置头部标签--> &l ...

  3. ORA-12801/ORA-12853: insufficient memory for PX buffers: current 274880K, max needed 19722240K/ORA-04031解决方法

    近日,现场一台服务器在运行时出现下列异常: ORA-12801: error signaled in parallel query server P139 ORA-12853: insufficien ...

  4. Learning-Python【6】:Python数据类型(2)—— 列表、元组

    一.列表类型 1.用途:记录多值,比如人的多个爱好 2.定义方式:在[ ]内用逗号分隔开多个任意类型的值 li = [1, 2, 3] 3.常用操作+内置方法 优先掌握的操作: 1)按索引存取值:可以 ...

  5. 去除pt种里tracker的方法

    1.下载BEncode Editor,打开 2.把下载的种子拖进去,可以看到这样的: tracker就是箭头指的地方,这个包含了个人帐号独一无二的私钥,如果泄露给别人的话别人下载就是走的你的帐号,轻则 ...

  6. _skill,_skill_category

    _skill,_skill_category -- 自定义商业技能-- 小技巧:配合增加自定义商业技能._add skill [ID _skill `skillId`商业技能ID `skillIcon ...

  7. gym 101081 E. Polish Fortress 几何

    E. Polish Fortress time limit per test 2.0 s memory limit per test 256 MB input standard input outpu ...

  8. 【shell脚本】 变量基础学习整理

    1.linux系统环境 echo 'echo /etc/profile ' >> /etc/profile echo 'echo /etc/bashrc' >> /etc/ba ...

  9. 函数, arguments对象, eval,静态成员和实例成员

    函数创建: 3种创建函数的方式    * 直接声明函数 function funcName(/*参数列表*/){ //函数体 } * 函数表达式 var funcName = function(){ ...

  10. 19、Squid代理服务器

    第十九章,配置Squid服务器 一.代理服务器简介 19.1.1:什么是代理服务器 代理服务器的功能就是代理网络用户去取的网络信息,好比是网络信息的中转站,大多被用来连接互联网和局域网.代理服务器好像 ...