图的存储结构可以有邻接矩阵,邻接表,十字链表,多重链表
一.图的邻接表表示
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-------------