图的存储有4种形式:邻接矩阵,前向星,邻接表,链式前向星(属于邻接表)
1.链接矩阵
这个是我们最常用的,开一个map[i][j]
初始化 map[i][i]=0,map[i][j]=inf;
初始化需要o(n*n),建图 m
缺点 :遍历效率较低,并且不能存储重边,
初始化效率低;图的空间开销大。
2.前向星把边存在数组中,按照起点顺序排序;
用head数组去存以个个边为起点的第一个点。
#include<iostream> #include<stdio.h> #include<algorithm> #include<string.h> using namespace std; struct node { int from; int to; int w; }edge[10000]; bool cmp(node a,node b) { if(a.to==b.to&&a.from==b.from) return a.w<b.w; if(a.from==b.from) return a.to<b.to; return a.from<b.from; } int head[10000];//记录以 vi开始的第一条边的位子; int n,m; int main() { cin>>n>>m;//n个点,m条边 memset(head,-1,sizeof head); for(int i=0;i<m;i++) { cin>>edge[i].from>>edge[i].to>>edge[i].w; } sort(edge,edge+m,cmp); head[0]=0; for(int i=1;i<m;i++) { if(edge[i].from!=edge[i-1].from) head[edge[i].from]=i; }//建图 for(int i=1;i<=n;i++) { for(int k=head[i];edge[k].from==i&&k<m;k++) { cout<<edge[k].from<<" "<<edge[k].to<<" "<<edge[k].w<<endl; } } return 0; }
时间复杂度mlogm 空间 m+n;
优点:可以应对点非常多的情况,可以存储重边;
缺点:不能判断任意2个顶点 vi和vj之间是否有边。
3.邻接表
邻接表 有3种实现:动态建表实现,使用stl中的vector模拟链表实现和静态建表实现。
① 动态建表
#include <iostream> using namespace std; struct EdgeNode { int to; int w; EdgeNode *next; }; struct VEdgeNode { int from; EdgeNode *frist; }alist[10000]; int main() { int n,m; cin>>n>>m; for(int i=1;i<=n;i++) { int a,b,c; cin>>a>>b>>c; EdgeNode *p=new EdgeNode(); p->to=b; p->w=c; p->next=alist[a].frist; alist[a].frist=p; } for(int i=1;i<=m;i++) { for(EdgeNode *k=alist[i].frist;k!=NULL;k=k->next) { cout<<i<<" "<<k->to<<" "<<k->w<<endl; } } return 0; }
② vector模拟链表
#include<iostream> #include<vector> using namespace std; struct node { int to; int w; }; vector<node>map[10000]; int main() { int n,m; cin>>n>>m; for(int i=1;i<=n;i++) { int a,b,c; cin>>a>>b>>c; node e; e.to=b; e.w=c; map[a].push_back(e); } for(int i=1;i<=m;i++) { for(vector <node>::iterator it=map[i].begin();it!=map[i].end();it++) { cout<<i<<" "<<it->to<<" "<<it->w<<endl; } } return 0; }
③静态建表(链式前向星)
#include<iostream> using namespace std; int head[10000]; struct node { int to; int w; int next; }Edge[100000]; int main() { int n,m; cin>>n>>m; for(int i=1;i<=m;i++) { head[i]=-1; } for(int i=1;i<=n;i++) { int a,b,c; cin>>a>>b>>c; Edge[i].to=b; Edge[i].w=c; Edge[i].next=head[a]; head[a]=i; } for(int i=1;i<=m;i++) { for(int k=head[i];k!=-1;k=Edge[k].next) { cout<<i<<" "<<Edge[k].to<<" "<<Edge[k].w<<endl; } } return 0; }