用户操作
[即时聊天] [发私信] [加为好友]
alai04ID:alai04
94438次访问,排名1046,好友0人,关注者2人。
alai04的文章
原创 29 篇
翻译 52 篇
转载 0 篇
评论 79 篇
alai04的公告
EMAIL: alai04@gmail.com

MSN: alai04@hotmail.com

Google 网上论坛
boost_doc_translation
访问此论坛

最近评论
egmkang:对你们辛苦劳动致敬!!!
egmkang:对你们辛苦劳动致敬!!!
gzlyb:谢谢达达的辛勤劳作!
yshuise:向你们致敬,你们做的事勘称伟大!!
cs2213:cs2213@gmail.com
算我一个
文章分类
    收藏
      相册
      文章图片
      C++
      boost文档翻译项目
      C++的罗浮宫
      C类语言讨论与研究圈
      STL中文站(RSS)
      艺术编程
      存档
      软件项目交易
      订阅我的博客
      XML聚合  FeedSky
      订阅到鲜果
      订阅到Google
      订阅到抓虾
      订阅到BlogLines
      订阅到Yahoo
      订阅到GouGou
      订阅到飞鸽
      订阅到Rojo
      订阅到newsgator
      订阅到netvibes

      原创 源代码BFS_DFS_v1.6.hpp收藏

      新一篇: 用STL实现DFS/BFS算法——使用boost.Multi_Index容器 | 旧一篇: 用STL实现DFS/BFS算法——基于策略的类设计

      这次又有一点小的修改,主要是关于StateSpaceTreeSearch的第二个模板参数的。它是用于指定选用BFS还是DFS,原来我是让使用者选择BFSInserter和DFSInserter两者之一。后来想想,好象不应该让用户看到这两个结点插入策略,毕竟用户并不关心这一点。用户关心的仅是如何在BFS和DFS两者之间选择一个,所以我把选择的方法改为用一个bool常量来指定。

      把原来的SearchInserter模板参数改为一个非类型模板参数,命名为UseBFS,当它为true时就用BFS,否则就用DFS。再定义一个SearchInserter模板来根据bool参数选择相应的BFSInserter或DFSInserter,代码如下:


      // Filename: BFS_DFS_v1.6.hpp
      #ifndef _BFS_DFS_HPP
      #define _BFS_DFS_HPP

      #include <list>
      #include <vector>
      #include <set>
      #include <ext/hash_set>

      using std::list;
      using std::vector;
      using std::set;
      using __gnu_cxx::hash_set;
      using __gnu_cxx::hash;

      // 仿函式,用于不检查状态结点是否重复
      template <class T>
      struct NoCheckDup : std::unary_function<T, bool>
      {
          bool operator() (const T&) const
          {
              return false;
          }
      };

      // 仿函式,用vector容器检查状态结点是否重复,线性复杂度
      // 要求状态类提供operator==
      template <class T>
      class SequenceCheckDup : std::unary_function<T, bool>
      {
          typedef vector<T> Cont;
          Cont states_;
      public:
          bool operator() (const T& s)
          {
              typename Cont::iterator i =
                  find(states_.begin(), states_.end(), s);
              if (i != states_.end())  // 状态已存在,重复
              {
                  return true;
              }
              states_.push_back(s);  // 状态未重复,记录该状态
              return false;
          }
      };

      // 仿函式,用set容器检查状态结点是否重复,对数复杂度
      // 要求状态类提供operator<
      template <class T>
      class OrderCheckDup : std::unary_function<T, bool>
      {
          typedef set<T> Cont;
          Cont states_;
      public:
          bool operator() (const T& s)
          {
              typename Cont::iterator i = states_.find(s);
              if (i != states_.end())  // 状态已存在,重复
              {
                  return true;
              }
              states_.insert(i, s);  // 状态未重复,记录该状态
              return false;
          }
      };

      // 仿函式,用hash_set容器检查状态结点是否重复
      // 要求状态类提供operator==以及hash()成员函数
      template <class T>
      class HashCheckDup : std::unary_function<T, bool>
      {
          struct HashFcn
          {
              size_t operator()(const T& s) const { return s.hash(); }
          };
          typedef hash_set<T, HashFcn> Cont;
          Cont states_;
      public:
          HashCheckDup() : states_(100, HashFcn()) {}
          bool operator() (const T& s)
          {
              if (states_.find(s) != states_.end())  // 状态已存在,重复
              {
                  return true;
              }
              states_.insert(s);  // 状态未重复,记录该状态
              return false;
          }
      };

      // BFS算法对应的新结点插入策略
      template <class Cont>
      class BFSInserter
      {
      public:
          BFSInserter(Cont& c) : c_(c) {}
          typedef typename Cont::iterator iterator;
          typedef typename Cont::value_type value_type;
          void operator()(iterator it, const value_type& v) {
              c_.push_back(v);  //新结点插入到列表的末端,即未搜索的结点后
          }
      private:
          Cont& c_;
      };

      // DFS算法对应的新结点插入策略
      template <class Cont>
      class DFSInserter
      {
      public:
          DFSInserter(Cont& c) : c_(c) {}
          typedef typename Cont::iterator iterator;
          typedef typename Cont::value_type value_type;
          void operator()(iterator it, const value_type& v) {
              c_.insert(++it, v);  //新结点插入到未搜索的结点前
          }
      private:
          Cont& c_;
      };

      // 状态空间树搜索模板
      // State:问题状态类,提供nextStep()和isTarget()成员函数
      // UseBFS:可选择BFS或DFS,true为BFS,false为DFS,缺省为BFS
      // CheckDup:状态查重算法,可选择NoCheckDup,HashCheckDup,OrderCheckDup等
      template < class State, bool UseBFS = true,
          template <class> class CheckDup = NoCheckDup >
      class StateSpaceTreeSearch
      {
          template <class Cont, bool>
          struct SearchInserter
          {
              typedef DFSInserter<Cont> Inserter;
          };

          template <class Cont>
          struct SearchInserter<Cont, true>
          {
              typedef BFSInserter<Cont> Inserter;
          };

      public:
          typedef list<State> Cont;
          typedef typename Cont::iterator iterator;
          typedef typename SearchInserter<Cont, UseBFS>::Inserter Inserter;

          template <class Func>
          int operator()(const State& initState, Func afterFindSolution) const
          // initState : 初始化状态,类State应提供成员函数nextStep()和isTarget(),
          //             nextStep()用vector<State>返回下一步可能的所有状态,
          //             isTarget()用于判断当前状态是否符合要求的答案;
          // afterFindSolution : 仿函式,在找到一个有效答案后调用之,它接受一个
          //                     const State&,并返回一个bool值,true表示停止搜索,
          //                     false表示继续搜索
          // return : 找到的答案数量
          {
              CheckDup<State> checkDup;
              Cont states;
              Inserter inserter(states);
              states.push_back(initState);
              iterator head = states.begin();  //指向下个搜索的结点
              vector<State> nextStates;
              int n = 0;  //记录找到的解答数量
              bool stop = false;
              while (!stop && head != states.end())
              {
                  State s = *head;  //搜索一个结点
                  nextStates.clear();
                  s.nextStep(nextStates);  //从搜索点生成下一层结点
                  for (typename vector<State>::iterator i = nextStates.begin();
                       i != nextStates.end(); ++i)
                  {
                      if (i->isTarget())
                      {  // 找到一个目标状态
                          ++n;
                          if (stop = afterFindSolution(*i))  // 处理结果并决定是否停止
                          {
                              break;
                          }
                      } else {  // 不是目标状态,判断是否放入搜索队列中
                          if (!checkDup(*i))  // 只将不重复的状态放入搜索队列
                          {
                              inserter(head, *i);
                          }
                      }
                  }
                  ++head;  //指针移到下一个元素
              }
              return n;
          }
      };

      #endif


       相应地,使用者的代码也有所改变,以推箱子为例,如下:

      // soko.cpp -- 推箱子主程序

      #include <iostream>
      #include "BFS_DFS_v1.6.hpp"
      #include "SokoState_v1.h"

      using namespace std;

      bool printAnswer(const SokoState& s)
      {
          s.printAnswer(cout);
          cout << endl;
          return true;
      }

      template <class T>
      bool stopSearch(const T&)
      {
          return true;
      }

      int main(int argc, char *argv[])
      {
          SokoState initState;
          cin >> initState;
          cout << initState;
          StateSpaceTreeSearch<SokoState, true, OrderCheckDup> sokoSearch;
          int n = sokoSearch(initState, printAnswer);
          if (n == 0)
          {
              cout << "No answer." << endl;
          }
          return 0;
      }


       

      发表于 @ 2006年06月07日 15:50:00|评论(loading...)|编辑

      新一篇: 用STL实现DFS/BFS算法——使用boost.Multi_Index容器 | 旧一篇: 用STL实现DFS/BFS算法——基于策略的类设计

      评论:没有评论。

      发表评论  


      当前用户设置只有注册用户才能发表评论。如果你没有登录,请点击登录
      Csdn Blog version 3.1a
      Copyright © alai04