表示物件与物件之间的关系的数学对象,是图论的基本研究对象
数据结构之图
定义
二元组的定义
图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题目废话
表示两个物体之间的关系
衍生出树,堆,最短路等新的数据结构和算法