目录
图
图是由顶点与顶点之间的边组成的数据结构。
顶点相当于数据,便相当于数据之间的关系。
分两类:有向图 无向图
顶点的度:与顶点相连的边数。
有向图中:
分出度(从顶点出发)和入度(指向顶点)。
在有向图中,出度和等于入度和;
完全图
无向完全图:任意两个顶点都有边相连的无向图。
一个有n个顶点的无向完全图包包含n*(n-1)/2条边
有向完全图:任意两个顶点之间有两条方向相反的有向边相连
一个有n个顶点的有向完全图包包含n*(n-1)条边
连通图
普通的连通图:
是指任意一个顶点出发都能到达其他所有的顶点的无向图(n个顶点最少有n-1条边)。
强连通图:
在有向图中,沿着边的方向,从任意一个顶点出发都能到达其他所有的顶点。
要使一个有n条边,每个顶点的图不在连通,至少有删去n-m+2条边。
带权图
用数字来表示两顶点之间的关系强弱,权值越大,关系越强。
度的性质
在无向图或有向图中,顶点的度数总和为边数的两倍。
邻接矩阵
如果顶点i和顶点j之间存在边,则G[ i ][ j ]=1,否则等于0。
如果是带权图,那么G[ i ][ j ]=1为i和j之间的权值,若无边为0.
无向图的邻接矩阵,以主对角线为对称轴。
插入无向边:
G[ u ][ v ]=G[ v ][ u ]=1;
插入有向边:
G[ u ][ v ]=1;
图的遍历序列不唯一
深搜dfs遍历图(先序):
void dfs(int u){ //u为当前节点
vis[u]=true; //被搜过就标记
cout<<u<<endl;
for(int i=1;i<=n;i++){ //找所有与u相连的点
if(G[u][i]&&!vis[i]){ //如果还未被搜过
dfs(i); //搜索i
}
}
}
树
- 如果一个无向 连通 图中不存在回路(环),则称这个图为 树。
- 有根树(左下):树中有一个确定的根结点;
- 无根树(右下):根结点不确定,任何一个结点均可以作为根结点。
(因为树是有层次的,根结点就是最上层的一个结点。)
有根树
子树
图中某个结点及其下面的所有结点以及结点之间的边,被称为以该结点为根的子树,例如usr
、lib
、bin
就是/
的一棵子树,usr
是该子树的根。
度
每个结点拥有的子树个数我们称为结点的度,比如结点/
的度为 77,home
的度为 33。
结点之间的关系
在例子中,我们称usr
是lib
、bin
的父亲结点,lib
、bin
是usr
的孩子结点。
叶子结点
没有孩子的结点,也就是度为 00 的结点我们称为叶子,例如etc
、lib
、bin
都是叶子结点。
深度
我们规定根结点是树的第一层,树根的孩子结点是树的第二层,以此类推,树的深度就是结点的最大层数,例如例子里的树,它的深度为 44。
树的性质
一棵包含 𝑛 个结点的树(有根树/无根树)满足的一些性质:
- 若树上的结点数为 𝑛,则边数一定为 𝑛−1。
- 树上的任意一对结点之间 有且仅有 一条简单路径。
此外对于包含 𝑛 个结点的有根树的一些性质:
- 每棵非空有根树有且仅有一个根结点。
- 父结点可以有多个孩子结点,除根结点外,其余的结点有且仅有一个父结点。
- 根结点没有父结点,叶结点没有孩子结点。
边权
树是一种特殊的图,一棵树同时也是一个图。我们之前学习图的时候都知道有一种图叫做带权图。那么树作为图的一种,每条边自然也能被赋予权值。
叶子结点
树的叶子结点指的是没有任何孩子的结点,它可以有父亲,但是一定没有孩子。那么我们怎么判断叶子结点呢?很简单,既然它只有父亲没有孩子,那么和它相邻的点就一定只有父亲结点,因此,在树的点数大于 11的情况下 叶子结点在图上的度数必然为 1。利用这个性质可以很好的在树当中寻找出叶子结点。
需要注意区分树上的度和图上的度数的区别:树上的度指的是一个结点所拥有的子树数目,而图上的度数指的是一个结点所连接的边的条数。叶子结点在图上的度数必然为 1,而叶子结点不会有任何子树,所以在树上的度是 0。
距离
树上的每两个点之间有且只有一条简单路径,因此,我们定义树上的两个结点的距离为这两个点路径上的所有边的边权之和(在不带权图中就是经过的边的数量)。
求解方法:从两个点开始向根结点查找,找到第一公共祖先,就可以确定一条简单路径了。