zoukankan      html  css  js  c++  java
  • 图的优先级搜索

    上一篇博客里面提到了优先级搜索(priority first search),单独拿出来写一篇,因为优先级搜索可以适用大部分图搜算算法。所谓优先级搜索,是在图的遍历过程中,每次迭代都更新图中某些点或者是边的优先级,随着算法的不断推进调整,每次选取顶点或者边中优先级最高的那个元素进行访问。按照这种思想,深度优先搜索和广度优先搜索其实都可以纳入到这个框架中,因为他们的不同之处仅仅在于,每次选择点的时候,点的优先级策略是不同的。约定优先级数值越小,优先级越高。下面,给出优先级搜索的框架:

     1 template<typename Tv, typename Te> template<typename PU> void Graph<Tv, Te>::pfs(int s,PU prioUpdater)//优先级搜索
     2 {
     3     reset(); int clock = 0; int v = s;
     4     do
     5         if (stasus(v) == UNDISCOVERED)//遇到未发现的顶点
     6             PFS(v, clock);//执行一次pFS
     7     while (s != (v = (++v%n)));//做到不重不漏
     8 }
     9 template<typename Tv, typename Te> template<typename PU>//优先级更新器
    10 void Graph<Tv, Te>::PFS(int s, PU prioUpdater)
    11 {
    12     priority(s) = 0; status(s) = VISITED; parent(s) = -1;
    13     while (1)
    14     {
    15         for (int w = firstNbr(s); w > -1; w = nextNbr(s, w))//更新所有的邻接顶点
    16             prioUpdater(this, s, w);
    17         for(int shortest = INT_MAX, w = 0; w < n; w++)//在所有顶点中寻找优先级最低的顶点
    18             if(status(w) == UNDISCOVERED)
    19                 if (priority(w) < shortest)
    20                 {
    21                     shortest = priority(w);
    22                     s = w;
    23                 }
    24         if (status(s) == VISITED) break;//优先级最高的顶点已经被访问
    25         status(s) = VISITED; type(parent(s), s) = TREE;
    26     }
    27 }

    优先级搜索的流程,可以总结如下:对于当前节点的所有邻居,按照某种更新策略,更新他们的优先级;然后,从所有的点中找出优先级最高的顶点进行访问;当取出的优先级最高的顶点已经访问完成,算法结束。这样我们同样得到了和之前相同的,图的一颗遍历树。算法每次迭代都要访问所有的n个节点,时间复杂度为O(n^2)。

    下面,把BFS和DFS纳入这个框架中,它们的更新器如下:

     1 template <typename Tv, typename Te> struct BfsPU
     2 { 
     3     virtual void operator() ( Graph<Tv, Te>* g, int uk, int v ) 
     4     {
     5         if ( g->status ( v ) == UNDISCOVERED ) 
     6         if ( g->priority ( v ) > g->priority ( uk ) + 1 ) 
     7         {
     8              g->priority ( v ) = g->priority ( uk ) + 1; //更新优先级(数)
     9              g->parent ( v ) = uk; //更新父节点
    10         } 
    11     }
    12 }

    广度优先搜索,只需要每次将UNDISCOVERED的点,优先级设置为当前点优先级数+1,这样每次新发现的点都要比以前发现的点优先级低。

     template <typename Tv, typename Te> struct DfsPU
    { 
        virtual void operator() ( Graph<Tv, Te>* g, int uk, int v ) 
        {
             if ( g->status ( v ) == UNDISCOVERED ) 
             if ( g->priority ( v ) > g->priority ( uk ) - 1 ) 
             {
                  g->priority ( v ) = g->priority ( uk ) - 1; //更新优先级(数)
                  g->parent ( v ) = uk; //更新父节点
                  return;//这里只要有一个节点更新就可以返回
             } 
         }
    }        

    深度优先搜索,每次新发现的顶点都比父亲节点优先级低。要注意的是,每当有一个节点的优先级发生了改变,就可以直接返回。

  • 相关阅读:
    我爱Java系列之---【SpringBoot打成war包部署】
    279. Perfect Squares
    矩阵dfs--走回路
    112. Path Sum
    542. 01 Matrix
    106. Construct Binary Tree from Inorder and Postorder Traversal
    105. Construct Binary Tree from Preorder and Inorder Traversal
    Invert Binary Tree
    563 Binary Tree Tilt
    145 Binary Tree Postorder Traversal
  • 原文地址:https://www.cnblogs.com/lustar/p/7213711.html
Copyright © 2011-2022 走看看