怎样通过boost库的breadth

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了怎样通过boost库的breadth相关的知识,希望对你有一定的参考价值。

参考技术A 我这里使用了一个数组来表示单元格数据,如果在外面管理这些数据的话你可以使用指针更简单一些。现在我们已经有了一个可以用于 graph_traits 的表示矩阵的类型了,但是首先让我们定义一些我们需要的类型和函数:
namespace matrix

typedef size_t vertex_descriptor;

template< size_t ROWS, size_t COLS >
size_t get_row(
vertex_descriptor vertex,
graph< ROWS, COLS > const & )

return vertex / COLS;


template< size_t ROWS, size_t COLS >
size_t get_col(
vertex_descriptor vertex,
graph< ROWS, COLS > const & )

return vertex % COLS;


template< size_t ROWS, size_t COLS >
vertex_descriptor make_vertex(
size_t row,
size_t col,
graph< ROWS, COLS > const & )

return row * COLS + col;



遍历顶点的类型和函数:
namespace matrix

typedef const cell * vertex_iterator;

template< size_t ROWS, size_t COLS >
std::pair< vertex_iterator, vertex_iterator >
vertices( graph< ROWS, COLS > const & g )

return std::make_pair( g.cells, g.cells + ROWS*COLS );


typedef size_t vertices_size_type;

template< size_t ROWS, size_t COLS >
vertices_size_type
num_vertices( graph< ROWS, COLS > const & g )

return ROWS*COLS;



边类型:
namespace matrix

typedef std::pair< vertex_descriptor, vertex_descriptor > edge_descriptor;

bool operator==(
edge_descriptor const & lhs,
edge_descriptor const & rhs )

return
lhs.first == rhs.first && lhs.second == rhs.second ||
lhs.first == rhs.second && lhs.second == rhs.first;


bool operator!=(
edge_descriptor const & lhs,
edge_descriptor const & rhs )

return !(lhs == rhs);



最后,迭代器和函数来帮助我们遍历出顶点和边存在的关联关系:
namespace matrix

template< size_t ROWS, size_t COLS >
vertex_descriptor
source(
edge_descriptor const & edge,
graph< ROWS, COLS > const & )

return edge.first;


template< size_t ROWS, size_t COLS >
vertex_descriptor
target(
edge_descriptor const & edge,
graph< ROWS, COLS > const & )

return edge.second;


typedef boost::shared_container_iterator< std::vector< edge_descriptor > > out_edge_iterator;

template< size_t ROWS, size_t COLS >
std::pair< out_edge_iterator, out_edge_iterator >
out_edges(
vertex_descriptor vertex,
graph< ROWS, COLS > const & g )

boost::shared_ptr< std::vector< edge_descriptor > > edges( new std::vector< edge_descriptor >() );

if( g.cells[vertex] == FREE )

size_t
row = get_row( vertex, g ),
col = get_col( vertex, g );

if( row != 0 )

vertex_descriptor up = make_vertex( row - 1, col, g );

if( g.cells[up] == FREE )
edges->push_back( edge_descriptor( vertex, up ) );


if( row != ROWS-1 )

vertex_descriptor down = make_vertex( row + 1, col, g );

if( g.cells[down] == FREE )
edges->push_back( edge_descriptor( vertex, down ) );


if( col != 0 )

vertex_descriptor left = make_vertex( row, col - 1, g );

if( g.cells[left] == FREE )
edges->push_back( edge_descriptor( vertex, left ) );


if( col != COLS-1 )

vertex_descriptor right = make_vertex( row, col + 1, g );

if( g.cells[right] == FREE )
edges->push_back( edge_descriptor( vertex, right ) );



return boost::make_shared_container_range( edges );


typedef size_t degree_size_type;

template< size_t ROWS, size_t COLS >
degree_size_type
out_degree(
vertex_descriptor vertex,
graph< ROWS, COLS > const & g )

std::pair< out_edge_iterator, out_edge_iterator > edges = out_edges( vertex, g );
return std::distance( edges.first, edges.second );



到现在未知我们已经定义好了我们需要的 boost::graph_traits 结构
namespace boost

template< size_t ROWS, size_t COLS >
struct graph_traits< matrix::graph< ROWS, COLS > >

typedef matrix::vertex_descriptor vertex_descriptor;
typedef matrix::edge_descriptor edge_descriptor;

typedef matrix::out_edge_iterator out_edge_iterator;
typedef matrix::vertex_iterator vertex_iterator;

typedef boost::undirected_tag directed_category;
typedef boost::disallow_parallel_edge_tag edge_parallel_category;
struct traversal_category :
virtual boost::vertex_list_graph_tag,
virtual boost::incidence_graph_tag ;

typedef matrix::vertices_size_type vertices_size_type;
typedef matrix::degree_size_type degree_size_type;

static vertex_descriptor null_vertex() return ROWS*COLS;
;


接下来就是如何展示使用BFS算法查找最短路径:
int main()

const size_t rows = 8, cols = 8;

using namespace matrix;

typedef graph< rows, cols > my_graph;

my_graph g =

FREE, FREE, FREE, FREE, WALL, FREE, FREE, FREE,
WALL, FREE, FREE, FREE, FREE, FREE, FREE, FREE,
FREE, FREE, FREE, WALL, FREE, WALL, FREE, FREE,
FREE, WALL, FREE, WALL, FREE, FREE, FREE, FREE,
FREE, FREE, FREE, WALL, FREE, FREE, FREE, FREE,
FREE, FREE, FREE, WALL, FREE, FREE, WALL, FREE,
FREE, FREE, FREE, FREE, FREE, FREE, WALL, FREE,
FREE, FREE, FREE, FREE, FREE, FREE, WALL, FREE,
;

const vertex_descriptor
start_vertex = make_vertex( 5, 1, g ),
finish_vertex = make_vertex( 2, 6, g );

vertex_descriptor predecessors[rows*cols] = 0 ;

using namespace boost;

breadth_first_search(
g,
start_vertex,
visitor( make_bfs_visitor( record_predecessors( predecessors, on_tree_edge() ) ) ).
vertex_index_map( identity_property_map() ) );

typedef std::list< vertex_descriptor > path;

path p;

for( vertex_descriptor vertex = finish_vertex; vertex != start_vertex; vertex = predecessors[vertex] )
p.push_front( vertex );

p.push_front( start_vertex );

for( path::const_iterator cell = p.begin(); cell != p.end(); ++cell )
std::cout << "[" << get_row( *cell, g ) << ", " << get_col( *cell, g ) << "]\n" ;

return 0;


以下是输出的从起点到终点的最短路径:
[5, 1]
[4, 1]
[4, 2]
[3, 2]
[2, 2]
[1, 2]
[1, 3]
[1, 4]
[1, 5]
[1, 6]
[2, 6]
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/breadth_first_search.hpp>
#include <boost/graph/visitors.hpp>
#include <boost/shared_container_iterator.hpp>
#include <boost/shared_ptr.hpp>
#include <vector>
#include <boost/iterator/counting_iterator.hpp>
#include <list>

namespace matrix

typedef int cell;

static const int FREE = 0;
static const int WALL = 1;

template< size_t ROWS, size_t COLS >
struct graph

cell cells[ROWS*COLS];
;

typedef size_t vertex_descriptor;

template< size_t ROWS, size_t COLS >
size_t get_row(
vertex_descriptor vertex,
graph< ROWS, COLS > const & )

return vertex / COLS;


template< size_t ROWS, size_t COLS >
size_t get_col(
vertex_descriptor vertex,
graph< ROWS, COLS > const & )

return vertex % COLS;


template< size_t ROWS, size_t COLS >
vertex_descriptor make_vertex(
size_t row,
size_t col,
graph< ROWS, COLS > const & )

return row * COLS + col;


typedef const cell * vertex_iterator;

template< size_t ROWS, size_t COLS >
std::pair< vertex_iterator, vertex_iterator >
vertices( graph< ROWS, COLS > const & g )

return std::make_pair( g.cells, g.cells + ROWS*COLS );


typedef size_t vertices_size_type;

template< size_t ROWS, size_t COLS >
vertices_size_type
num_vertices( graph< ROWS, COLS > const & g )

return ROWS*COLS;


typedef std::pair< vertex_descriptor, vertex_descriptor > edge_descriptor;

bool operator==(
edge_descriptor const & lhs,
edge_descriptor const & rhs )

return
lhs.first == rhs.first && lhs.second == rhs.second ||
lhs.first == rhs.second && lhs.second == rhs.first;


bool operator!=(
edge_descriptor const & lhs,
edge_descriptor const & rhs )

return !(lhs == rhs);


template< size_t ROWS, size_t COLS >
vertex_descriptor
source(
edge_descriptor const & edge,
graph< ROWS, COLS > const & )

return edge.first;


template< size_t ROWS, size_t COLS >
vertex_descriptor
target(
edge_descriptor const & edge,
graph< ROWS, COLS > const & )

return edge.second;


typedef boost::shared_container_iterator< std::vector< edge_descriptor > > out_edge_iterator;

template< size_t ROWS, size_t COLS >
std::pair< out_edge_iterator, out_edge_iterator >
out_edges(
vertex_descriptor vertex,
graph< ROWS, COLS > const & g )

boost::shared_ptr< std::vector< edge_descriptor > > edges( new std::vector< edge_descriptor >() );

if( g.cells[vertex] == FREE )

size_t
row = get_row( vertex, g ),
col = get_col( vertex, g );

if( row != 0 )

vertex_descriptor up = make_vertex( row - 1, col, g );

if( g.cells[up] == FREE )
edges->push_back( edge_descriptor( vertex, up ) );


if( row != ROWS-1 )

vertex_descriptor down = make_vertex( row + 1, col, g );

if( g.cells[down] == FREE )
edges->push_back( edge_descriptor( vertex, down ) );


if( col != 0 )

vertex_descriptor left = make_vertex( row, col - 1, g );

if( g.cells[left] == FREE )
edges->push_back( edge_descriptor( vertex, left ) );


if( col != COLS-1 )本回答被提问者和网友采纳

使用 Boost 的图 breadth_first_search() 在未加权、无向图中查找路径

【中文标题】使用 Boost 的图 breadth_first_search() 在未加权、无向图中查找路径【英文标题】:Using Boost's graph breadth_first_search() to find a path in an unweighted, undirected graph 【发布时间】:2009-01-14 12:51:39 【问题描述】:

我正在使用 adjacency_list 图,具有无向和未加权的边。我需要找到顶点 u 和顶点 v 之间的最短路径。 我应该从你开始使用breadth_first_search() 吗?到达v时,如何获取路径,如何停止搜索?

谢谢!

【问题讨论】:

也许这将有助于开始:***.com/questions/14126/… 【参考方案1】:

是的,从你开始做breadth_first_search()。

FOR every vertex i meet
  IF i==v: BREAK
  record predecessor of i as i.p

要找到最短路径,从v开始:

PRINT_PATH(u, v)
  IF v==u
    print u
  ELSEIF v.p==NIL
    print 'no path from u to v exists'
  ELSE PRINT_PATH(u, v.p)
    print v

【讨论】:

【参考方案2】:

您应该使用最短路径算法之一,Dijkstra Shortest Path 是最合适的,因为您只需要找到两个顶点之间的路径。在 boost 发行版中有一个 example 用于它的用途。从该函数获取输出有多种选择:通过提供距离属性图或构建前驱图或编写自定义访问者。

【讨论】:

这个问题与未加权的图有关。要在未加权图中找到最短路径,最简单的方法是广度优先搜索。 Dijkstra 的算法解决了加权有向图上的单源最短路径问题。【参考方案3】:

您需要使用minimum spanning tree: 搜索算法。这是一个非常简单直接的贪心算法。

【讨论】:

如果我没记错的话,最小生成树不一定包含两个特定顶点之间的最短路径。 我认为大多数最小生成树算法都不是贪心的(在做出贪婪的、次优选择的意义上),但它们实际上找到了最优的最小生成树。 @dehmann 不正确。现在常用的算法有两种,Prim算法和Kruskal算法。两者都是在多项式时间内运行的贪心算法。贪婪并不意味着次优选择,它意味着在不考虑进一步步骤的情况下做出最佳表面选择。 @dehmann...en.wikipedia.org/wiki/Dijkstra's_algorithm 也是贪婪的(也是最优的)。 @JessePepper 是的,但肯定不能保证最小生成树为您提供两点之间的最佳路径。

以上是关于怎样通过boost库的breadth的主要内容,如果未能解决你的问题,请参考以下文章

windows下boost怎样安装与使用说明

Boost的某些库还是需要生成二进制的库的,必须安装才行,以及使用库的方法

Windows下Boost库的安装与使用

Boost库的分类

windows下boost库的基本用法

天猫品牌库的好处有哪些 怎样通过天猫品牌库