用STL实现DFS/BFS算法——检查重复状态

本文介绍了如何使用STL实现DFS和BFS算法,并着重讨论了在搜索过程中如何检查和处理重复状态。通过引入仿函数模板参数`checkDup`,允许用户自定义检查重复状态的方法。文章提供了三个示例:不检查、线性查找和有序容器查找。最后,还提到了使用hash_set进行查找,但需要用户自定义hash函数。
摘要由CSDN通过智能技术生成
用STL实现DFS/BFS算法
——检查重复状态
前几天,有网友留言说我使用“先深”、“先宽”的说法是狗屁二流子词汇,正确的说法应该是“深度优先”,“广度优先”。态度和用词虽然有点让人不好接受,但提的意见终归是有点道理的。请实话,我已经不记得最早是从哪里学来的“先深”、“先宽”,但可以肯定一点,本人是发明不出这样的词汇的,只是认为这两个词还不错,比较简单明了,所以就用上了。后来,我上GOOGLE查了一下,结果发现的确用四个字的比用两个字多得多,看来多数人还是喜欢长一点的词,或者说长一点的那两个词更通用一些。于是我就想是不是该“改正”一下自己的“错误”,换个大家更容易接受的词用用。
接下来,很高兴地看到有网友挺“先深”、“先宽”,于是我又想,如果我这就换了,岂不是有点对不起那些和我一样喜欢用“先深”、“先宽”的网友?思前想后,干脆用E文好了,所以就有了这个新的标题。
转入正题,前面我们说过,到目前为止我们的DFS/BFS算法还只能搜索无重复状态的状态空间树,而象下象棋、推箱子等问题,都会出现问题状态在几步之后可能会回到以前出现过的状态的情况。当重复状态出现时,我们必须能够识别出来,并且不应把它放入搜索树中。最简单、直接的做法就是,当问题状态类的nextStep()成员函数返回一组下一步可能状态时,我们对这些状态逐一进行检查,如果发现有重复的,就不把重复状态放入搜索树(即不入栈或入队列)。至于如何检查重复状态,我们还是采用函数模板最常见的方法,让使用者自己提供检查的方法,在我们的DFS/BFS算法中用一个泛型的模板参数来指定它。这样一来,我们的算法会变为这样(以BFS为例):
template <class T1, class T2, class T3 >
int BreadthFirstSearch(const T1& initState, const T2& afterFindSolution,
    T3& checkDup)
// 前两个参数与旧版本相同
// checkDup :  仿函式,对于每一个下一步可能的状态调用之,它接受一个const T1&,
//             并返回一个Boolean值,true表示状态重复,false表示状态不重复
// return : 找到的答案数量
{
 int n = 0;
 queue<T1> states;
 states.push(initState);
 
 vector<T1> nextStates;
 bool stop = false;
 while (!stop && !states.empty())
 {
      T1 s = states.front();
      states.pop();
      nextStates.clear();
      s.nextStep(nextStates);
      for (typename vector<T1>::iterator i = nextStates.begin();
           i != nextStates.end(); ++i)
      {
          if (i->isTarget())
          { // 找到一个目标状态
              ++n;
              if (afterFindSolution(*i)) // 处理结果并决定是否停止搜索
              {
                  stop = true;
                  break;
              }
          } else { // 不是目标状态,判断是否放入搜索队列中
              if (!checkDup(*i)) //
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值