图的认识与存储

图的认识

组成

图主要是有一个二元组组成 G=<V,E>,V表示节点集,E表示边集,w表示一条边上的权值(自己定义)

方向

图分 有向图和无向图

有向图

所有边集都是有方向的,比如A->B,A可以到B,但是B到不了A;

无向图

所有边集都是没有方向的,比如A<–>B,A可以到B且B可以到A。

度数

无向图

无向图某点的度数指这个点连出的边数,无向图出度=入度

有向图

有向图出度不一定等于出度

图的存储

点非常好存,可边就不好存了,不过我们可以将边去转化为两个点。

邻接矩阵

存储原理

邻接矩阵用的是二维数组去存储图的边;
a [ i ] [ j ]表示节点i到节点j有一条边,权值为a[ i ] [ j ]

代码模板

//无向图
//定义
const int maxn=1e3+10;
int a[maxn][maxn];

//...
//加边
for(int i=1;i<=m;i++){
	int u,v;
	scanf("%d%d",u,v);
	a[u][v]=1;
	a[v][u]=1;//根据题目要求,有向图不加这行代码
}

邻接表

存储原理

邻接表可根据对边的需求,进行开空间,类似队列;

代码模板

#include<bits/stdc++.h>
using namespace std;

const int maxn=1e3+10;
int n,m;
//定义
vector< pair<int,int> >e[maxn];
int main(){
	scanf("%d%d",&n,&m);
	//加边
	for(int i=1;i<=m;i++){
		int u,v,w;
		scanf("%d%d%d",&u,&v,&w);
		e[u].push_back(make_pair(v,w));
		e[v].push_back(make_pair(u,w));//根据题目要求,有向图不加这行代码
	}
	//调用操作
	for(int i=1;i<=n;i++){
		for(int j=0;j<e[i].size();j++){
			//…… 
		}
	}
	return 0;
}

链式前向星

存储原理

将与某点有关的边,存入一个链表中

代码模板

#include<bits/stdc++.h>
using namespace std;

const int maxn=1e3+10;
int n,m,tot;
//定义
int head[maxn];
struct node {
	int v,w,nxt;
}e[maxn];
void add(int u,int v,int w){
	e[++tot].v=v;//更新边数记录新边弧头
	e[tot].w=w;//记录权值
	e[tot].nxt=head[u];//插入链表
	head[u]=tot;//更新指针
}
int main(){
	scanf("%d%d",&n,&m);
	//加边
	for(int i=1;i<=m;i++){
		int x,y,z;
		scanf("%d%d%d",&x,&y,&z);
		add(x,y,z);
		add(y,x,z);
	}
	for(int i=head[u];i;i=e[i].nxt){
	//......
	}
	return 0;
} 

图的存储总结

  1. 邻接矩阵
    空间复杂度O(n^2)
    查边时间复杂度O(1)

  2. 邻接表
    空间复杂度O(n)
    查边时间复杂度O(n)
    空间不稳定
    ps:邻接表空间一般会给你开两倍

  3. 链式前向星
    空间复杂度O(n)
    查边复杂度O(n)
    空间稳定

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

materialistOier

我只是一名ssfoier

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值