数据结构5 - 图


一、基本术语
  • G = (V, E) vertex: n = |V| edge|arc: e = |E|
  • 同一条边的两个顶点彼此邻接
  • 同一顶点自我邻接,构成自环
  • 不含自环,即为简单图
  • 顶点与其所属的边彼此关联
  • 度:与同一顶点关联的边数
  • 若邻接顶点u和v的次序无所谓,则(u, v) 为无向边
  • 所有边均无方向的图,即无向图;反之,有向图中均为有向边
二、邻接矩阵(Vector< Vector< vertex )

matrix: 记录顶点之间的邻接关系

一一对应:矩阵元素和图中可能存在的边,A(i, j) = 1则表示顶点i和j之间存在一条边,A(i, j) = 0则表示不存在边

三、邻接表(Vector< List< vertex )

邻接表,存储方法跟树的孩子链表示法相类似,是一种顺序分配和链式分配相结合的存储结构。如这个表头结点所对应的顶点存在相邻顶点,则把相邻顶点依次存放于表头结点所指向的单向链表中。

四、双连通分量:判定准则
  • 无向图的关节点:删除之后,原图的连通分量增多
  • 无关节点的图,称作双(重)连通图
  • 极大的双连通子图,称作双连通分量
五、优先级搜索
template <typename Tv, typename Te> template <typename PU> //优先级搜索(全图)
	void Graph<Tv, Te>::pfs ( int s, PU prioUpdater ) { //assert: 0 <= s < n
    reset(); int v = s; //刜始化
	do //逐一检查所有顶点
		if ( UNDISCOVERED == status ( v ) ) //一旦遇刡尚未収现癿顶点
			PFS ( v, prioUpdater ); //即从诠顶点出収启劢一次PFS
	while ( s != ( v = ( ++v % n ) ) ); //按序号检查,故丌漏丌重
}

template <typename Tv, typename Te> template <typename PU> //顶点类型、边类型、优先级更新器
void Graph<Tv, Te>::PFS ( int s, PU prioUpdater ) { //优先级搜索(单个连通域)
	priority ( s ) = 0; status ( s ) = VISITED; parent ( s ) = -1; //初始化,起点s加至PFS树中
	while ( 1 ) { //将下一顶点和边加至PFS树中
		for ( int w = firstNbr ( s ); -1 < w; w = nextNbr ( s, w ) ) //枚举s的所有邻居w
			prioUpdater ( this, s, w ); //更新顶点w的优先级及其父顶点
		for ( int shortest = INT_MAX, w = 0; w < n; w++ )
			if ( UNDISCOVERED == status ( w ) ) //从尚未加入遍历树的顶点中
				if ( shortest > priority ( w ) ) //选出下一个
					{ shortest = priority ( w ); s = w; } //优先级最高的顶点s
		if ( VISITED == status ( s ) ) break; //直至所有顶点均已加入
		status ( s ) = VISITED; type ( parent ( s ), s ) = TREE; //将s及不其父的联边加入遍历树
	}
} //通过定义具体的优先级更新策略prioUpdater,即可实现不同的算法功能
六、Dijkstra算法:最短路径

设G=(V,E)是一个带权有向图,把图中顶点集合V分成两组,第一组为已求出最短路径的顶点集合(用S表示,初始时S中只有一个源点,以后每求得一条最短路径﹐就将加入到集合S中,直到全部顶点都加入到S中,算法就结束了),第二组为其余未确定最短路径的顶点集合(用u表示),按最短路径长度的递增次序依次把第二组的顶点加入S 中。在加入的过程中,总保持从源点v到S中各顶点的最短路径长度不大于从源点v到U中任何顶点的最短路径长度。此外,每个顶点对应一个距离,S中的顶点的距离就是从v到此顶点的最短路径长度,U中的顶点的距离,是从v到此顶点只包括S中的顶点为中间顶点的当前最短路径长度。

不能有负权边

template <typename Tv, typename Te> struct DijkstraPU { //针对Dijkstra算法的顶点优先级更新器
	virtual void operator() ( Graph<Tv, Te>* g, int uk, int v ) {
    	if ( UNDISCOVERED == g->status ( v ) ) //对于uk每一尚未被发现的邻接顶点v,按Dijkstra策略
			if ( g->priority ( v ) > g->priority ( uk ) + g->weight ( uk, v ) ) { //做松弛
				g->priority ( v ) = g->priority ( uk ) + g->weight ( uk, v ); //更新优先级
				g->parent ( v ) = uk; //并同时更新父节点
			} 
	} 
};
七、Prim算法:最小支撑树
template <typename Tv, typename Te> struct PrimPU { //Prim算法的顶点优先级更新器
	virtual void operator() ( Graph<Tv, Te>* g, int uk, int v ) { //对uk的每个
    	if ( UNDISCOVERED == g->status ( v ) ) //对于uk每一尚未被发现的邻接顶点v,按Prim策略
			if ( g->priority ( v ) > g->weight ( uk, v ) ) { //做松弛
				g->priority ( v ) = g->weight ( uk, v ); //更新优先级
				g->parent ( v ) = uk; //并同时更新父节点
			} 
	} 
};
八、Floyd-Warshal算法

给定带权网络G,计算其中所有点对之间的最短距离

(计算所有点对之间的最短距离,执行n次Dijkstra也可以,且复杂度均为O(n³))优点:形式简单、算法紧凑、便于实现;允许负权边

for k in range(0, n) 
	for u in range(0, n) 
		for v in range(0, n) 
			A[u][v] = min( A[u][v], A[u][k] + A[k][v] );
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值