四种常见的建图方法
1.邻接矩阵
直接开一个N*N的矩阵如果i,j相连则将二维矩阵赋值,否则则为INF,虽然简单直观但是遍历效率过低,并且不能存储重边,遇到点较稀疏的图时空间利用率过低,时间复杂度为O(N*N)
2.前向星
将所有边排序并记录每个顶点第一条边的位置,从而实现的存储和遍历。可以储存重边但是不可以直接判断两个节点是否相连,时间复杂度为O(M*logM)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
int N,M;
struct node{
int from,to,w;
}G[105];
int head[105];
bool cmp(node a,node b){
if(a.from==b.from&&a.to==b.to)
return a.w<b.w;
if(a.from==b.from)
return a.to<b.to;
return a.from<b.from;
} //排序使找到每个节点
int main(){
int i,j,k;
scanf("%d%d",&N,&M);
for(i=0;i<M;i++)
scanf("%d%d%d",&G[i].from,&G[i].to,&G[i].w);
memset(head,-1,sizeof(head));
sort(G,G+M,cmp);
head[G[0].from]=0;
for(i=1;i<M;i++)
if(G[i].from!=G[i-1].from)
head[G[i].from]=i; //每个节点第一条边的位置
for(i=1;i<=N;i++){ //图的遍历
for(k=head[i];G[k].from==i&&k<M;k++) //因为涉及排序所以复杂度为O(M*logM)
printf("%d %d %d\n",G[k].from,G[k].to,G[k].w);
}
return 0;
}
3.邻接表
将每一个顶点所连的边组成一条单链表,每条单链表称为这个节点的邻接表,有两种实现方式,时间复杂度为O(M)
(1).动态链表
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
int N,M;
struct node{
int to,w;
node *next;
};
struct edge{
node *first;
}G[105];
int main(){
int i,j,x,y,z;
scanf("%d%d",&N,&M);
for(i=0;i<M;i++){
scanf("%d%d%d",&x,&y,&z);
node *p=new node;
p->to=y;
p->w=z;
p->next=G[x].first; //每条边连在当前节点的前一条边上
G[x].first=p; //形成一个链式储存结构,first为当前节点的最后
} //一条边
node *k;
for(i=1;i<=N;i++){ //图的遍历
for(k=G[i].first;k!=NULL;k=k->next)
printf("%d %d %d\n",i,k->to,k->w);
}
return 0;
}
(2).用vector实现
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
int N,M;
struct node{
int to,w;
};
vector<node> G[105];
int main(){
int i,j,x,y,z;
scanf("%d%d",&N,&M);
for(i=0;i<M;i++){
scanf("%d%d%d",&x,&y,&z);
G[x].push_back((node){y,z});
}
for(i=1;i<=N;i++){
for(j=0;j<G[i].size();j++)
printf("%d %d %d\n",i,G[i][j].to,G[i][j].w);
}
return 0;
}
4.链式前向星
通过数组模拟邻接表,是建图和遍历效率较高的一种方法,时间复杂度为O(M)
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
int N,M;
struct node{
int to,w,next;
}G[105];
int head[105];
int main(){
int i,j,x,y,z;
scanf("%d%d",&N,&M);
memset(head,-1,sizeof(head));
for(i=0;i<M;i++){
scanf("%d%d%d",&x,&y,&z);
G[i].to=y;
G[i].w=z;
G[i].next=head[x];
head[x]=i; //与前向星相同,当前边连接当前节点的
} //前一条边
for(i=1;i<=N;i++){
for(j=head[i];j!=-1;j=G[j].next) //head[i]为i节点最后一条边的位置
printf("%d %d %d\n",i,G[j].to,G[j].w);
}
return 0;
}