6.3优先级搜索、最短路径、最小生成树

一、优先级搜索

  • 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;
	}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值