图的存储方式之前向星与邻接表
常用的邻接矩阵和邻接表都挺简单的,就不提了。 这个是ACM版本的前向星,本质就是用数组替换了链表,效果就是更方便一些。 虽然不如十字链表删除方便,但是也能比较方便地写出边删除的操作。
//前向星
struct graph{
typedef vector<int> VI;
VI info,next,to;
//假设现在有n个点,m条边,info长度为n,next和to长度为m。
//其中,info保存着所有节点的第一个边
//next保存着所有边信息的下一个边
//to保存着边的下一个节点信息。如果是带权边,可以增加一个weights数组,与to类似。(所有边增加主要加的是to)
graph(int n=0,int m=0):to(0),next(0){
info.resize(n);
next.reserve(m);
to.reserve(m);
}
int edge_size(){
return to.size();//显然,to即保存了所有边的信息
}
int vertex_size(){
return info.size();//info保存了所有节点的信息
}
void expand(int i){
if(info.size()<i+1)
info.resize(i+1);
}
void add(int i,int j){//添加一条从i到j的边,有向
expand(i),expand(j);
to.push_back(j);//压入新边的信息
next.push_back(info[i]);//新头的下一个指向原来的指针
info[i] = to.size()-1;//链表头指针指向新加项目
}
void del_back(){
for(int i=0;i<info.size();i++){
if(info[i] == to.size()-1){
info[i] = next.back();
break;
}
}
to.pop_back();
next.pop_back();
}
void clear(){
info.clear();
next.resize(0);
to.resize(0);
}
};
想了一下还是提一下邻接表吧
struct Edge{
int from,to,weight;
};
vector<Edge> G[maxn];//可以用来模拟邻接表
//使用的时候给对应的数组G[node]插入边即可,其实也挺方便的
另外一个是刘汝佳的蓝书里面的实现,应该也是邻接表,只是G[maxn][edgeNum]
里面放的不再是直接放边对象,而是改为了边索引号n。这个索引号可以由边对象数组维护,也可以由多个数据对象数组维护,比较方便。在很多时候,对边的信息没有过多要求时,直接用一两个int数组就可以表示全其信息,也比较方便。唯一的问题是不好删除。