图论基础1

1.图的基本概念

图是一种数据结构,定义为 G = ( V, E).

V是一个非空有限集合,代表顶点(结点);

E代表边的集合,对于边( u,v)\in E

        -u和v邻接(adjacent)

        -e和u、v关联(lncident)

无向图(undirected graph):图的边没有方向,双向可达。

有向图(directed graph):图的边有方向,只能按箭头方向从一点到另一点。

带权图:权的含义,不加权的图 也可以认为所有边上的权都是1.

阶:一个图的阶是指图中顶点的个数.

度:与该顶点相关联的边的数目,有奇点、偶点之分,对于有向图,有入度和出度之分.

定理:无向图中所有顶点的度之和等于边数的2倍;

           有向图中所有顶点的入度之和等于所有顶点的出度之和;

            任意一个无向图一定有偶数个(或0个奇点);

完全图:一个n阶的完全无向图含有n*(n-1)/2条边;

               一个n阶的完全有向图含有n*(n-1)条边;

稠密图:当一个图的边数接近完全图时;

稀疏图:当一个图的边数远远少于完全图时;

在具体使用时,要选用不同的存储结构。

连通:如果图中结点U、V之间存在一条从U通过若干条边、点到达结点V的通路,则称U、V是连通的。

回路:起点和终点相同的路径,称为回路,或“环”.

子图(subgraph):边的子集和相关联的点集。

强连通分量:在有向图G中,如果两个顶点vi,v间(vi>vj)有 一条从vi到vj的 有向路径,同时还有一条从vj到vi的有向路径,则称两个顶点强连通(strongly connected)。如果有向图G的每两个项点都强连通,称G是一个强连通图。

2.图的存储和遍历

2.1 图的存储方式1:邻接矩阵

  • adjacency matrix A
  • n x n
  •                       
  • 在稀疏图中造成大量的空间浪费
  • 遍历邻接边时造成时间浪费

2.2 图的存储方式2:边集数组

        利用一维数组存储图中所有边的一种图的表示方法,每个数组元素存储一条边的起点 、终点和权值。

        在边集数组中查找一条边或一个顶点的度都需要扫描整个数组,其时间复杂度为O(E),

E为边数。

        适合对边依次进行处理的运算,而不适合对顶点的运算和对任意一条边的运算,从空间复杂度上讲,边集数组适合于存储稀疏图。

2.3 图的存储方式3:邻接表

  • Adjacency table
  • 空间复杂度 为O(e/n)
  • 扫描整个表 时间复杂度为O(n+e)

//adjacency List for undirected graph
const int N = le5+5;
const int M = 2e5+5;
int head[N],to[M] ,nx[M], cost[M],tot;
void init(){
	memset(head, -1,sizeof(head));
	tot = 0;
}
int addEdge(int u, intv, int c){
	to[tot] = v; cost[tot] = c; nx[tot] = head[u]; head[u] = tot++;
	to[tot] = u; cost[tot] = c; nx[tot] = head[v]; head[v] = tot++;
}
//traversal
for(int i = head[u]; ~i; i = nx[i]){
	int v = to[i], c = cost[i];
	//do something...
}

空间复杂度:O(V+E)

对稀疏图可以减少存储空间,可以直接访问到一个点的查找/删除边不是常数时间,图的信息一般都不做修改。

2.4图的存储方式4:VECTOR存边

vetcor 动态数组 本质是邻接表

vetcor<pair<int, int> >e[n]

//undirected graph with weight                          //undirected graph with weight                           
typedef pair<int, int> pii;								const int N = le5+5;
const int N = le5+5;									vetcor<int> e[N];
vetcor<pii> e[N];
		
//addEdge <u,v>(c)										//addEdge <u,v>
e[u].push_back({v,c});									e[u].push_back(v);
e[v].push_back({u,c});									e[v].push_back(u);

//traversal												//traversal
for(int i = 0;i < e[u].size(); i++){					for(int i = 0;i < e[u].size(); i++){
	int v = e[u][i].first, c = e[u][i].second;			int v = e[u][i];
	//do something...										//do something...
	}													}            

  • 16
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值