四种建图方法

四种常见的建图方法

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;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值