源程序BFS_DFS_v1.hpp

在引入boost.Multi_index容器,我想有必要先整理一下DFS/BFS的代码。主要的修改是,不再使用queue容器和stack容器,而用list容器来替换它们。原因是,queue和stack容器会把已搜索过的结点删除掉,而我们如果要在容器内进行查重的话,就必须保留所有结点,所以不能使用这两种容器。

一开始我也想过使用vector容器,不过由于我们最终的目标是Multi_index容器,它不能象vector那样进行随机访问,它只能实现list容器的功能,为了便于向Multi_index过渡,最终我还是选择了list。

没有了queue和stack,我们就要用一个iterator来区分list中那些已搜索与未搜索的结点。我把已搜索和未搜索的结点分别放在list的两端,而这个iterator指向它们的分界线,即iterator之前的结点为已搜索结点,之后的结点为未搜索结点。当我们需要取出下一个结点来处理时,只要把iterator后移一下就可以了;对当前结点调用nextStep()所得到的下一层结点,则要视DFS或BFS来决定如何插入list;如果是DFS,就把新得到的结点插入到iterator的后面;如果是BFS,则把新的结点插入到list的后端;当iterator到达list的末端时,则表示搜索结束。

为方便起见,我把DFS和BFS以及各种查重算法集中到一个.hpp文件,源码如下:

 


 

// Filename: BFS_DFS_v1.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;
    }
};

// 仿函式,用hash_set容器检查状态结点是否重复
// 要求状态类提供operator==以及hash函数
template <class T, class HashFcn = hash<T> >
class HashCheckDup : std::unary_function<T, bool>
{
    typedef hash_set<T, HashFcn> Cont;
    Cont states_;
public:
    typedef typename Cont::hasher hasher;
    HashCheckDup(const hasher& hf) : states_(100, hf) {}
    bool operator() (const T& s)
    {
        if (states_.find(s) != states_.end())  // 状态已存在,重复
        {
            return true;
        }
        states_.insert(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;
    }
};

// 仿函式,用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;
    }
};

template <class T1, class T2 >
int BreadthFirstSearch(const T1& initState, const T2& afterFindSolution)
// 两参数版本
// initState : 初始化状态,类T1应提供成员函数nextStep()和isTarget(),
//             nextStep()用vector<T1>返回下一步可能的所有状态,
//             isTarget()用于判断当前状态是否符合要求的答案;
// afterFindSolution : 仿函式,在找到一个有效答案后调用之,它接受一个const T1&,
//                     并返回一个Boolean值,true表示停止搜索,false表示继续找
// return : 找到的答案数量
{
    NoCheckDup<T1> noCheckDup;
    return BreadthFirstSearch(initState, afterFindSolution, noCheckDup);
}

template <class T1, class T2, class T3 >
int BreadthFirstSearch(const T1& initState, const T2& afterFindSolution,
    T3& checkDup)
// 三参数版本,前两个参数参考两参数版本说明
// checkDup :  仿函式,对于每一个下一步可能的状态调用之,它接受一个const T1&,
//             并返回一个Boolean值,true表示状态重复,false表示状态不重复
//             checkDup的缺省值是不进行检查,假定所有生成的状态均不会重复
// return : 找到的答案数量
{
    int n = 0;
    list<T1> states;
    states.push_back(initState);
    typename list<T1>::iterator head = states.begin();  //指向下个搜索的结点

    vector<T1> nextStates;
    bool stop = false;
    while (!stop && head != states.end())
    {
        T1 s = *head;  //搜索一个结点
        nextStates.clear();
        s.nextStep(nextStates);  //从搜索点生成下一层结点
        for (typename vector<T1>::iterator i = nextStates.begin();
             i != nextStates.end(); ++i)
        {
            if (i->isTarget())
            {  // 找到一个目标状态
                ++n;
                if (stop = afterFindSolution(*i))  // 处理结果并决定是否停止
                {
                    break;
                }
            } else {  // 不是目标状态,判断是否放入搜索队列中
                if (!checkDup(*i))  // 只将不重复的状态放入搜索队列
                {
                    states.push_back(*i);
                }
            }
        }
        ++head;  //指针移到下一个元素
    }
    return n;
}

template <class T1, class T2 >
int DepthFirstSearch(const T1& initState, const T2& afterFindSolution)
// 两参数版本
// initState : 初始化状态,类T1应提供成员函数nextStep()和isTarget(),
//             nextStep()用vector<T1>返回下一步可能的所有状态,
//             isTarget()用于判断当前状态是否符合要求的答案;
// afterFindSolution : 仿函式,在找到一个有效答案后调用之,它接受一个const T1&,
//                     并返回一个Boolean值,true表示停止搜索,false表示继续找
// return : 找到的答案数量
{
    NoCheckDup<T1> noCheckDup;
    return DepthFirstSearch(initState, afterFindSolution, noCheckDup);
}

template <class T1, class T2, class T3 >
int DepthFirstSearch(const T1& initState, const T2& afterFindSolution,
    T3& checkDup)
// 三参数版本,前两个参数参考两参数版本说明
// checkDup :  仿函式,对于每一个下一步可能的状态调用之,它接受一个const T1&,
//             并返回一个Boolean值,true表示状态重复,false表示状态不重复
//             checkDup的缺省值是不进行检查,假定所有生成的状态均不会重复
// return : 找到的答案数量
{
    int n = 0;
    list<T1> states;
    states.push_back(initState);
    typename list<T1>::iterator head = states.begin();  //指向下个搜索的结点

    vector<T1> nextStates;
    bool stop = false;
    while (!stop && head != states.end())
    {
        T1 s = *head;
        nextStates.clear();
        s.nextStep(nextStates);
        for (typename vector<T1>::iterator i = nextStates.begin();
             i != nextStates.end(); ++i)
        {
            if (i->isTarget())
            {  // 找到一个目标状态
                ++n;
                if (stop = afterFindSolution(*i))  // 处理结果并决定是否停止
                {
                    break;
                }
            } else {  // 不是目标状态,判断是否放入搜索队列中
                if (!checkDup(*i))  // 只将不重复的状态放入搜索队列
                {
                    typename list<T1>::iterator it = head;
                    states.insert(++it, *i);  //插入到head的后面
                }
            }
        }
        ++head;
    }
    return n;
}

#endif


源代码要使用GCC编译,其中使用了STL的扩展容器hash_set,如果使用其它编译环境,则需要修改相应的头文件和容器名字空间。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
代码解读void bfs() { while (!q.empty()) { Node cur = q.top(); q.pop(); if (cur.box_x == end_x && cur.box_y == end_y) { best = cur.step; flag = true; break; } else for (int i = 0; i < 4; i++) { flag1 = false; memset(visit2, 0, sizeof(visit2)); int x = cur.box_x + dx[i]; int y = cur.box_y + dy[i]; if (x<1 || y<1 || x>n || y>m || board[x][y] == 1) continue; Node next; next.box_x = x; next.box_y = y; next.people_x = cur.box_x; next.people_y = cur.box_y; next.step = cur.step + 1; if (i == 0) if (cur.box_y - 1 > 0) if (board[cur.box_x][cur.box_y - 1] != 'S' && bfs2(cur.box_x, cur.box_y - 1, cur.box_x, cur.box_y, cur.people_x, cur.people_y) && !visit[x][y][cur.box_x][cur.box_y - 1]) { visit[x][y][cur.box_x][cur.box_y - 1] = 1; q.push(next); } if (i == 1) if (cur.box_y + 1 <= m) if (board[cur.box_x][cur.box_y + 1] != 'S' && bfs2(cur.box_x, cur.box_y + 1, cur.box_x, cur.box_y, cur.people_x, cur.people_y) && !visit[x][y][cur.box_x][cur.box_y + 1]) { visit[x][y][cur.box_x][cur.box_y + 1] = 1; q.push(next); } if (i == 2) if (cur.box_x - 1 > 0) if (board[cur.box_x - 1][cur.box_y] != 'S' && bfs2(cur.box_x - 1, cur.box_y, cur.box_x, cur.box_y, cur.people_x, cur.people_y) && !visit[x][y][cur.box_x - 1][cur.box_y]) { visit[x][y][cur.box_x - 1][cur.box_y] = 1; q.push(next); } if (i == 3) if (cur.box_x + 1 <= n) if (board[cur.box_x + 1][cur.box_y] != 'S' && bfs2(cur.box_x + 1, cur.box_y, cur.box_x, cur.box_y, cur.people_x, cur.people_y) && !visit[x][y][cur.box_x + 1][cur.box_y]) { visit[x][y][cur.box_x + 1][cur.box_y] = 1; q.push(next); } } } }
07-14
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值