Boost中的图(1)

图的存储结构可以有邻接矩阵,邻接表,十字链表,多重链表

一.图的邻接表表示

1.邻接表adjacency_list的类模板

adjacency_list<OutEdgeList,VertexList,Directed,VertexProperties,EdgeProperites,GraphProperties,EdgeList>
OutEdgeList 表示出边容器类,可以是vecS--数组,listS-链表,setS,mapS,multisetS,mulmapS,hash_setS,hash_multisetS,has_multimapS
VertexList,表示节点容器类,同上;
Directed ,表示图的类型,可以是 undirectedS,directedS,bidirectionalS,第一个表示无向图,后两个表示有向图
VertexProperties,表示节点属性,
EdgeProperites,表示边属性
GraphProperties,表示图属性

注意:如果vertexList是vecS,需要小心删除节点,不能直接在遍历中删除,可以想见遍历时删除一个节点,那么下面一个节点怎么办?方法是采用List作为节点容器,具体代码参加下例。

2.关联数据类型

节点类型:用来描述节点
graph_traits<adjacency_list>::vertex_descriptor
边类型:用来描述边
graph_traits<adjacency_list>::edge_desciptor
节点遍历器
graph_traits<adjacency_list>::vertex_iterator
return by vertices 
边遍历器
graph_traits<adjacency_list>::edge_iterator
return by edges
出边遍历器:针对某个节点
graph_traits<adjacency_list>::out_edge_iterator
return by out_edges
入边遍历器:针对某个节点
graph_traits<adjacency_list>::in_edge_iterator
return by in_edges
graph_traits<adjacency_list>::adjacency_iterator
相邻点遍历器
graph_traits<adjacency_list>::inv_adjacency_iterator
反向相邻点遍历器:比如v->u,则v是u的反向相邻点,反向相邻点只有对无向图或者双向有向图有效。
节点计数类型
graph_traits<adjacency_list>::vertices_size_type
边计数类型
graph_traits<adjacency_list>::edges_size_type
度计数类型
graph_traits<adjacency_list>::degree_size_type
属性类型:用来定义描述点,边,图属性的属性
property_map<adjacency_list,property>::type
property_map<adjacency_list,property>::const_type
graph_property<adjacency_list,property>::type 

3.邻接表函数

3.1构造函数

假如Graph_lv是如下定义
typedef adjacency_list<listS,vecS,directedS> Graph_lv;
构造空的邻接表 
adjacency_list(const GraphProperty&p=GraphProperty());
例子:Graph_lv g;
构造N个节点的邻接表
adjacency_list(vertices_size_type n);
例子:Graph_lv g(N);
复制邻接表
adjacency_list(const adjacency_list&x);
例子:Graph_lv g(g);
首边,末边,节点数,边数构造; 
adjacency_list(EdgeIterator first,EdgeIterator last,vertices_size_type n,edges_size_type m=0);
例子:Graph_lv g(g_edges,g_edges+n_edges,N);
首边,末边,边属性,节点数,边数来构造;
adjacency_list(EdgeIterator firs,EdgeIterator last,EdgePropertyIterator ep_iter,vertices_size_type n=0,edges_size_type m=0);
例子:Graph_lv g(g_edges,g_edges+n_edges,weights,n_nodes),

3.2类其他函数

删除所有节点和边
clear()
交换两个图的节点,边和属性
swap(adjacency_list &x)

3.3非成员函数

获得遍历节点函数:
std::pair<vertex_iterator,vertex_iterator>vertices(const adjacency_list&)
返回值是这个图的节点的范围
例如:boots::tie(it,it_end)=boost::vertices(g);

获得遍历边的函数:
std::pair<vertex_iterator,vertex_iterator>edges(const adjacency_list&)

获得某点的相邻点函数
std::pair<vertex_iterator,vertex_iterator>adjacent_vertices(vertex_descriptor u,const adjacency_list&g)

获得某点的入边函数
std::pair<in_edge_iterator,in_edge_iterator>in_edges(vertex_descriptor v,const adjacency_list&g)
获得某点的出边函数
std::pair<out_edge_iterator,out_edge_iterator>out_edges(vertex_descriptor v,const adjacency_list&g)
获得某边的起点函数
vertex_descriptor source(edge_desciptor e,const adjacency_list &g)
获得某点的终点函数
vertex_descriptor target(edge_desciptor e,const adjacency_list)
获得某点出度函数
degree_size_type out_degree(vertex_descriptor u,const adjacency_list&g)
获得某点入度函数
degree_size_type in_degree(vertex_descriptor u,const adjacency_list)
获得某点的度函数
degree_size_type degree(vertex_descriptor u,const adjacency_list)
获得图的节点数目函数
vertices_size_type num_vertices(const adjacency_list &g)
获得图的边数目函数
edges_size_type num_edges(const adjacency_list&g)
判断节点u和v之间存在边的函数,结果返回真假
std::pair<edge_desciptor,bool> edge(vertex_descriptor u,vertex_descriptor v,const adjacency_list &g)
获得节点u和v之间的多条出边
std::pair<out_edge_iterator,out_edge_iterator>edge_range(vertex_descriptoru,vertex_descriptor v,const adjacency_list &g)

修改表函数

增加边函数:
std::pair<edge_desciptor,bool>add_edge(vertex_descriptor u,vertex_descriptor v,adjacency_list &g)
增加带边属性的增加边函数
std::pair<edge_desciptor,bool> add_edge(vertex_descriptor u,vertex_descriptor v,EdgeProperites &p,adjacency_list &g)
依据节点删除边函数
void remove_edge(vertex_descriptor u,vertex_descriptor v,adjacency_list &g)
直接删除边函数
void remove_edge(edge_desciptor e,adjacency_list &g)

属性相关函数

获得属性函数:
templete <class PropertyTag> property_map<adjacency_list,PropertyTag>::type get(PropertyTag,adjacency_list&g)

测试代码

Makefile

tag=test
srcs=main.cpp  test_graph.cpp
objs=$(srcs:%.cpp=%.o)
CC?=g++
cppflags=-g -c -Wall -I /usr/local/include/boost/ 
ldflags=-g -lstdc++ -lboost_regex -lboost_serialization -lm 
%.o:%.cpp
    $(CC) $(cppflags) $<  -o $@
$(tag):$(objs)
    $(CC) $(objs) -o $(tag) $(ldflags)
all:$(tag)
clean :rm -f $(objs) $(tag)

test_graph.cpp

#include<iostream>
using namespace std;
#include<boost/config.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <fstream>
#include <boost/archive/text_oarchive.hpp>
using namespace boost;
typedef adjacency_list<vecS,vecS,bidirectionalS,property<vertex_color_t,int,property<vertex_degree_t,int> > > Graph_vv;
//typedef adjacency_list<vecS,vecS,directedS> Graph_vv;
typedef adjacency_list<listS,listS,directedS> Graph_ll;
typedef adjacency_list<listS,vecS,directedS,no_property,property<edge_weight_t,int,property<edge_weight2_t,int> > > Graph_lv;
typedef std::pair<int,int> E;
enum{a,b,c,d,N};
char name[][20]={"节点-合肥","节点-北京","节点-上海","节点-杭州","节点-无效"};
struct first_name_t{
    typedef vertex_property_tag kind;
};
namespece
typedef property<first_name_t,std::string> vertex_firstname;
typedef adjacency_list<vecS,vecS,directedS,vertex_firstname> myGraph_vv;
int test_graph1();
int test_graph2();

int test_graph(){
    cout<<"Sta Test Graph-------------"<<endl;
    cout<<"Sta Graph use adjacency_list---"<<endl;
    test_graph1();
    test_graph2();
    cout<<"End Graph use adjacency_list---"<<endl;
    cout<<"End Test Graph-------------"<<endl;
    return 0;
}

int test_graph1(){
    E g_edges[]={E(a,b),E(b,c),E(c,a),E(d,a)};
    const int n_edges=sizeof(g_edges)/sizeof(E);

    myGraph_vv g(N);

    Graph_vv g(N);
    int i;
    cout<<"test 1"<<endl;
    cout<<"本图为有向图"<<endl;
    for(i=0;i<n_edges;i++){
        add_edge(g_edges[i].first,g_edges[i].second,g);
        cout<<"add edge("<<g_edges[i].first<<","<<g_edges[i].second<<")"<<endl;
    }
    cout<<"num_edges:"<<num_edges(g)<<endl;

    cout<<"查询边"<<endl;
    graph_traits<Graph_vv>::edge_iterator e_it,e_it_end;
    boost::tie(e_it,e_it_end)=boost::edges(g);
    while(e_it!=e_it_end){
        cout<<"边: "<<*e_it<<endl;
        e_it++;
    }

    graph_traits<Graph_vv>::vertex_iterator it,it_end;
    boost::tie(it,it_end)=boost::vertices(g);
    graph_traits<Graph_vv>::vertex_descriptor vd;
    graph_traits<Graph_vv>::degree_size_type in_degree_count,out_degree_count,degree_count;
    cout<<"查询每个节点的入度与出度"<<endl;
    while(it!=it_end){
        vd=vertex(*it,g);
        in_degree_count=in_degree(vd,g);
        out_degree_count=out_degree(vd,g);
        degree_count=degree(vd,g);
        cout<<name[*it]<<":"<<*it<<",入度:"<<in_degree_count<<",出度:"<<out_degree_count<<",度:"<<degree_count<<endl;
        it++;
    }
    cout<<"通过节点属性,查询每个节点的度"<<endl;
    property_map<Graph_vv,vertex_degree_t>::type deg=get(vertex_degree,g);
    property_map<Graph_vv,vertex_color_t>::type color=get(vertex_color,g);
    boost::tie(it,it_end)=vertices(g);
    while(it!=it_end){
        //deg[*it]=degree(*it,g);
        put(vertex_color,g,*it,1);
        cout<<name[*it]<<" 度:"<<get(deg,*it)<<",color: "<<color[*it]<<endl;
        put(vertex_degree,g,*it,1);
        it++;
    }
    graph_traits<Graph_vv>::out_edge_iterator oe_it,oe_it_end;
    vd=vertex(a,g);//look for a out_edges
    boost::tie(oe_it,oe_it_end)=out_edges(vd,g);
    cout<<name[vd]<<"出边为"<<endl;
    while(oe_it!=oe_it_end){
        cout<<*oe_it<<endl;
        oe_it++;
    }
    graph_traits<Graph_vv>::in_edge_iterator ie_it,ie_it_end;
    vd=vertex(a,g);//look for a out_edges
    boost::tie(ie_it,ie_it_end)=in_edges(vd,g);
    cout<<name[vd]<<"入边为"<<endl;
    while(ie_it!=ie_it_end){
        cout<<*ie_it<<endl;
        ie_it++;
    }
    std::ofstream ofs("test1.sn");
    boost::archive::text_oarchive oa(ofs);
    //oa<<g;
    return 0;
}
int test_graph2(){
    E g_edges[]={E(a,b),E(b,c),E(c,a)};
    const int n_edges=sizeof(g_edges)/sizeof(E);
    const int n_nodes=N;
    int weights[]={100,200,300};
    Graph_lv g(g_edges,g_edges+n_edges,weights,n_nodes);
    cout<<"test 2"<<endl;
    cout<<"本图为带权有向图"<<endl;
    cout<<"num_edges:"<<num_edges(g)<<endl;
//  property_map<Graph_lv,edge_weight_t>::type weightmap=get(edge_weight,g);

    graph_traits<Graph_lv>::vertex_iterator it,it_end,next;
    boost::tie(it,it_end)=boost::vertices(g);
    for(next=it;it!=it_end;it=next){
        cout<<name[*it]<<endl;
        //remove_vertex(*it,g);
        ++next;
    }

    property_map<Graph_lv,edge_weight_t>::type ew=get(edge_weight,g);
    property_map<Graph_lv,edge_weight2_t>::type ew2=get(edge_weight2,g);
    graph_traits<Graph_lv>::edge_iterator e_it,e_it_end;
    boost::tie(e_it,e_it_end)=boost::edges(g);
    while(e_it!=e_it_end){
        cout<<"edge :"<<*e_it<<",weight "<<ew[*e_it]<<",weight2 "<<ew2[*e_it]<<endl;
        //or you cat get weitht like this:cout<<get(ew,*e_it);
        e_it++;
    }

    Graph_lv::edges_size_type es;
    //graph_traits<Graph_lv>::edges_size_type es;

    return 0;

}

运行

hello world
Sta Test Graph-------------
Sta Graph use adjacency_list---
test 1
本图为有向图
add edge(0,1)
add edge(1,2)
add edge(2,0)
add edge(3,0)
num_edges:4
查询边
边: (0,1)
边: (1,2)
边: (2,0)
边: (3,0)
查询每个节点的入度与出度
节点-合肥:0,入度:2,出度:1,度:3
节点-北京:1,入度:1,出度:1,度:2
节点-上海:2,入度:1,出度:1,度:2
节点-杭州:3,入度:0,出度:1,度:1
通过节点属性,查询每个节点的度
节点-合肥 度:0,color: 1
节点-北京 度:0,color: 1
节点-上海 度:0,color: 1
节点-杭州 度:0,color: 1
节点-合肥出边为
(0,1)
节点-合肥入边为
(2,0)
(3,0)
test 2
本图为带权有向图
num_edges:3
节点-合肥
节点-北京
节点-上海
节点-杭州
edge :(0,1),weight 100,weight2 0
edge :(1,2),weight 200,weight2 0
edge :(2,0),weight 300,weight2 0
End Graph use adjacency_list---
End Test Graph-------------
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值