一、优先级搜索
- Priority First Search
- 不同的遍历算法的区别,取决于顶点的选取策略。不同的顶点选取策略,取决于存放和提供顶点的数据结构。
- 每个顶点都有初始的优先级数,并可能随着算法的推进而调整。通常的习惯是,优先级数越大/小,优先级越低/高
- 特别的,priority(v) == INT_MAX, 意味着v的优先级最低
- 统一框架
template<typename Tv, typename Te>
template <typename PU>//优先级更新器(函数对象)
void Graph<Tv, Te>::pfs(int s, PU prioUpdater){//PU的策略,更新顶点的优先级
priority(s) = 0; status(s) = VISITED; parents(s) = -1;//起点s加至PFS树中
while(1){//将下一顶点和边加至PFS树中
/*...依次引入n - 1个顶点(和n-1条边)...*/
//while
}//如何推广至非连通图
while(1){//依次引入n-1个顶点(和n-1条边)
for(int w = firstNbr(s); -1 < w; w = nextNbr(s, w)//对s各邻居
prioUpdater(this, s, w);//更新顶点w的优先级及其父顶点
for(int shortest = INT_MAX, w = 0; w < n; w++)
if(UNDISCOVERER == status(w)//从尚未加入遍历树的顶点中
if(shortest > priority(w))//选出下一个
{shortest = priority(w); s = w;}//优先级最高的顶点s
if(VISITED == status(s)) break;//直至所有顶点均以加入
status(s) = VISITED; type(parent(s), s) = TRUE;//将s加入遍历树
}//while
二、Dijkstra算法:最短路径树
- 问题加应用
- 给定:连通有向图G及其中的顶点u和v
- 找到:从u到v的最短路径及其长度
- 旅行者规划最经济的出行路线,路由器最快的将数据包传送到目标位置,多边形区域内的自主机器人进行路径规划
- 给定顶点s,计算s到其余各个顶点的最短路径及长度
不是致力于完工具,而是致力于创造工具。一个工具的发展趋于完善时,寻求突破在于创造新的工具,否则终将受限于计算模型。
- 单调性+假想实验
- 任一最短路径的前缀,也是一条最短路径
- 什么时候,如果已经有k个点离开了桌面,第k+1个点是谁(减而治之)
- PFS
- 套用PFS框架,为将Tk扩充至Tk+1,只需选出优先级最高的跨边ek及其对应顶点vk,并将其加入Tk,随后更新Vk\Vk+1中所有顶点的优先级数
- 注意,优先级数随后可能改变的顶点,必与vk邻接
- 因此,只需枚举vk的每一邻接顶点v,并取priority(v) = min(priority(v), priority(vk) + ||vk, v||)
- 以上完全符合PFS框架,唯一要做的工作无非是按照prioUpdater()规范,编写一个优先级更新器
- prioUpdater()
g->pfs(0, DijkstraPU<char, int>());//从顶点0出发,启动Dijkatra算法
template<typename Tv, typename Te>struct DijkPU{//Dijkstra算法的顶点优先级更新器
virtual void operator()(Graph<Tv, Te>* g, int uk, int v){//对uk的每个
if(UNDISCOVERED != g->status(v)) return;//尚未被发现的邻居v,按
if(g->priority(v) > g->priority(uk) + g->weight(uk, v)){//Dijkstra
g->priority(v) = g->priority(uk) + g->weight(uk, v);//策略
g->parent(v) = uk;//做松弛
}
}
}
三、prim算法:最小生成树
- 最小支撑树
- 连通网络N = (V; E)的子图T = (V; F)
- 支撑/spanning = 覆盖N中所有顶点
- 树,连通且无环,|V| = |F| + 1;加边出单环,再删除同环边即恢复为树;删边不连通,再加联通边即恢复为树
- 同一网络的支撑树不唯一
- 对负边也适用
- 应用:电信公司,假设电信线路使之覆盖全国;网络设计师
- 割&极短跨边
- 设(U; V \ U)是N的一个割(Cut),即将点集划分为两个集合
- 若uv是该割的一条极短跨边,则必存在一颗包含uv的MST
- 递增式构造,套用PFS框架
- 选出优先级最高的跨边ek及其对应顶点vk,并将其加入Tk,随后,更新V\Vk中所有顶点的优先级
- 注意,优先级数随后可能改变的顶点,必与vk邻接
- 因此,只需枚举vk的每一邻接顶点v,并取priority(v) = min(priority(v), ||vk, v||)
- 以上完全符合PFS规范,唯一要做的就是按照prioUpdate()规范,编写一个改变优先级的函数
//PrioUpdate()
g->pfs(0, PrimPU<char, int>());//从顶点0出发, 启动Prim算法
template<typename Tv, typename Te> struct PrimPU{//Prim算法的顶点优先及更新器
virtual void operator()(Graph<Tv, Te>* g, int uk, int v){//对uk的每个
if(UNDISCOVERED != g->status(v)) return;//尚未发现的邻居v,按
if(g->priority(v) > g->weight(uk, v)){//Prim
g->priority(v) = g->weight(uk, v);//策略
g->parent(v) = uk;
}
}