数据结构之图

表示物件与物件之间的关系的数学对象,是图论的基本研究对象

定义

二元组的定义

图G是一个有序二元组(V,E),其中V称为顶集(Vertices Set),E称为边集(Edges set),E与V不相交。它们亦可写成V(G)和E(G)。
E的元素都是二元组,用(x,y)表示,其中x,y∈V。 [1]

三元组的定义

图G是指一个三元组(V,E,I),其中V称为顶集,E称为边集,E与V不相交;I称为关联函数,I将E中的每一个元素映射到
。如果e被映射到(u,v),那么称边e连接顶点u,v,而u,v则称作e的端点,u,v此时关于e相邻。同时,若两条边i,j有一个公共顶点u,则称i,j关于u相邻。

大白话

一些点,用线连起来,即可称为图,点里存着数,线有长度

分类

有/无向图

如果给图的每条边规定一个方向,那么得到的图称为有向图。在有向图中,与一个节点相关联的边有出边和入边之分。相反,边没有方向的图称为无向图。

单图

一个图如果任意两顶点之间只有一条边(在有向图中为两顶点之间每个方向只有一条边);边集中不含环,则称为单图。

基本术语

阶(Order)

图G中点集V的大小称作图G的阶。

子图(Sub-Graph)

当图G’=(V’,E’)其中V‘包含于V,E’包含于E,则G’称作图G=(V,E)的子图。每个图都是本身的子图。

生成子图(Spanning Sub-Graph)

指满足条件V(G’) = V(G)的G的子图G’。

导出子图(Induced Subgraph)

以图G的顶点集V的非空子集V1为顶点集,以两端点均在V1中的全体边为边集的G的子图,称为V1导出的导出子图;以图G的边集E的非空子集E1为边集,以E1中边关联的顶点的全体为顶点集的G的子图,称为E1导出的导出子图。

度(Degree)

一个顶点的度是指与该顶点相关联的边的条数,顶点v的度记作d(v)。

入度(In-degree)和出度(Out-degree)

对于有向图来说,一个顶点的度可细分为入度和出度。一个顶点的入度是指与其关联的各边之中,以其为终点的边数;出度则是相对的概念,指以该顶点为起点的边数。

自环(Loop)

若一条边的两个顶点为同一顶点,则此边称作自环。

路径(Path)

从u到v的一条路径是指一个序列v0,e1,v1,e2,v2,…ek,vk,其中ei的顶点为vi及vi - 1,k称作路径的长度。如果它的起止顶点相同,该路径是“闭”的,反之,则称为“开”的。一条路径称为一简单路径(simple path),如果路径中除起始与终止顶点可以重合外,所有顶点两两不等。

行迹(Trace)

如果路径P(u,v)中的边各不相同,则该路径称为u到v的一条行迹。

轨道(Track)

如果路径P(u,v)中的顶点各不相同,则该路径称为u到v的一条轨道。
闭的行迹称作回路(Circuit),闭的轨称作圈(Cycle)。
(另一种定义是:walk对应上述的path,path对应上述的track。Trail对应trace。)

桥(Bridge)

若去掉一条边,便会使得整个图不连通,该边称为桥。

图的存储

数组(邻接矩阵)存储表示(有向或无向)

int g[1010][1010];
int u,v,w;
cin>>u>>v>>w;
g[u][v]=w;

表示u连向v(有向),边权值为w。
如果要连无向图就交换位置再连一条

int g[1010][1010];
int u,v,w;
cin>>u>>v>>w;
g[u][v]=w;
g[v][u]=w;

但邻接矩阵有点浪费空间,当一个图为稀疏图时,许多空间都用不到,一般为o(n*n)空间复杂度;

邻接表存储

用二维动态数组加结构体(当有权值时)来存

struct node{
	int v;
	int w;
	node(int vv,int ww){
		v=vv;
		w=ww;
	}
}

vector<vector<node> > g;
int u,v,w;
cin>>u>>v>>w;
g[u].push_back(node(v,w));

u数组里有v,表示u连向v,u不连向的不存进去就可以了,这会节约大量时间
结构体只是用于存边权,当没有边权时,直接push_back(v)即可
如果要存无向图,直接再交换u和v一遍即可

struct node{
	int v;
	int w;
	node(int vv,int ww){
		v=vv;
		w=ww;
	}
}

vector<vector<node> > g;
int u,v,w;
cin>>u>>v>>w;
g[u].push_back(node(v,w));
g[v].push_back(node(u,w));

图的遍历

图存下后自然要遍历的那存着干什么,下文以邻接表的遍历来演示(用邻接矩阵来存浪费时间又浪费空间)。

bfs

用bfs来在图上搜索,自然是先遍历所以向连的,再以第一个遍历的为起点依次向下遍历。

queue<int> q;
q.push(su);
while(!q.empty()){
	int u=q.front();
	q.pop();
	for(int i=0;i<g[u].size();i++){
		int v=g[u][i].v;
		int w=g[u][i].w;
		if(!vis[v]){
			vis[v]=1;//标记已经走过的
			q.push(v);
		}
	}
}

dfs

沿着已经知道可以走到的点一直往下走,直到无法向下走或走到已经走过的点就返回上一次位置

void dfs(int u){
	for(int i=0;i<g[u].size();i++){
		int v=g[u][i].v;
		int w=g[u][i].w;
		if(!vis[v]){
			vis[v]=1;
			dfs(v);
		}
	}
}

图的使用

AC题目废话
表示两个物体之间的关系
衍生出树,堆,最短路等新的数据结构和算法

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值