最基本而典型的图搜索算法包括:广度优先搜索(BFS),深度优先搜索(DFS),优先级搜索等(PFS),本文主要介绍图的优先级搜索(priority-first search,DFS),本文使用的图数据结构参见之前博客https://blog.csdn.net/qq_18108083/article/details/84870399
策略:从之前介绍的广度优先搜索和深度优先搜索中,可以发现这两种算法的框架具有一定的相似性,这两种算法的差异性体现在每一步迭代中对新顶点的选取策略不同,每一种选取策略都等效为,给所有顶点赋予不同的优先级,而且优先级随着算法的推进不断调整,在每一步迭代所选取的顶点,都是当时的优先级最高者,其实这个思想就是所谓的优先级搜索。
实现:由于整个图可能具有多个连通域,从单个顶点开始的PFS可能不能遍历到图中的所有顶点,所以PFS函数能够遍历从顶点s开始的单个连通域,而pfs函数则对所有顶点进行检查,只要未曾被访问过,就从该点开始一次新的PFS搜索,这样就能保证所有的连通域都能够被遍历到。
template<typename Tv, typename Te> template<typename PU> void graph<Tv, Te>::PFS(int s, PU prioUpdater) //(单个连通域)优先级搜索
{
priority(s) = 0; //设置s的优先级最高
status(s) = VISITED; //标记顶点s为已经便利的
cout << "选中的顶点:" << vdata(s) << endl;
parent(s) = -1; //这句可以不要,因为reset()已经置-1
while (true)
{
for (int w = firstNbr(s); w > -1; w = nextNbr(s, w)) //遍历顶点s的所有邻居
{
prioUpdater(this, s, w); //更新顶点w的优先级和父顶点
}
for (int shortest = INT_MAX, w = 0; w < n; w++)
{
if (status(w) == UNDISCOVERED) //如果顶点w尚未被遍历
if (priority(w) < shortest)
{
shortest = priority(w);
s = w; //更新级数最小的点
}
}
if (status(s) == VISITED) break; //如果所有顶点均已经访问,则结束
status(s) = VISITED;
cout << "选中的顶点:"<<vdata(s) << endl;
cout << parent(s) << endl;
type(parent(s), s) = TREE;
}
}
template<typename Tv, typename Te> template<typename PU> void graph<Tv, Te>::pfs(int s, PU prioUpdater)
{
reset();
int v = s;
do
{
if (status(v) == UNDISCOVERED)
PFS(v, prioUpdater);
} while ((v = (++v%n)) != s);
}
效率:若图G=(V,E)中共有n个顶点和e条边,则PFS仅需O(n^2)时间。