数据结构-第六章 图

本文详细介绍了图的基本概念,包括有向图、无向图、简单图和多重图,以及度、路径和连通性的概念。接着讨论了图的存储方法,如邻接矩阵、邻接表和十字链表等,以及它们的性能分析。此外,还涵盖了图的遍历算法,如BFS和DFS,以及最小生成树的Prim和Kruskal算法。最后,提到了有向无环图(DAG)的拓扑排序和关键路径分析。
摘要由CSDN通过智能技术生成

图的基本概念

图的定义

  1. 图G顶点集V边集E构成。
  2. |V|:顶点个数,也称图的阶
  3. 线性表可以是空表,树可以是空树,但图不可以是空,(V一定是非空集,E可以为空)
  1. 有向图
  1. 有向边(弧):顶点的有序对。
  2. <v,w> 弧尾:v;弧头:w。
  3. <v, w> ≠ <w, v>
  4. <v,w> :从v到w的弧 / v邻接到w
  1. 无向图
  1. 无向边(边):无序对:(v,w)或(w,v)
  2. (v, w) = (w, v)
  3. (v,w):w和v互为邻接点 / 边(w,v)依附于w和v / 边(v,w)和v,w相关联
  1. 简单图、多重图

简单图
① 不存在重复边;
② 不存在顶点到自身的边
在这里插入图片描述

多重图
图G中某两个结点之间的边数多于一条,又允许顶点通过同一条边和自己关联,则G为多重图
在这里插入图片描述


  1. 无向图:

无向图

  1. 顶点v的度是指依附于该顶点的边的条数,记为TD(v)
  2. 无向图的全部顶点的度的和等于边数的2倍

有向图:

有向图

  1. 入度是以顶点v为终点的有向边的数目,记为ID(v);
  2. 出度是以顶点v为起点的有向边的数目,记为OD(v)。
  3. 顶点v的度等于其入度和出度之和,即TD(v) = ID(v) + OD(v)。
    在这里插入图片描述
  1. 顶点-顶点关系描述
  1. 路径:顶点vp 到顶点vq之间的一条路径是指顶点序列
  2. 回路:第一个顶点和最后一个顶点相同的路径称为回路或环
  3. 简单路径:顶点不重复出现的路径称为简单路径
  4. 路径长度:路径上边的数目
  5. 无向图中,若从顶点v到顶点w有路径存在,则称v和w是连通的
  6. 有向图中,若从顶点v到顶点w和从顶点w到顶点v之间都有路径,则称这两个顶点是强连通
  1. 子图

在这里插入图片描述
子图:部分顶点和边
在这里插入图片描述
生成子图:包含所有顶点
在这里插入图片描述

  1. 连通分量:
    无向图中的极大连通子图称为连通分量
    在这里插入图片描述有向图中的极大强连通子图称为有向图的强连通分量
    在这里插入图片描述

  2. 生成树
    连通图的生成树是包含图中全部顶点的一个极小连通子图(边尽可能的少,但要保持连通)

|E|大于n-1,一定有回路
在这里插入图片描述

  1. 生成森林
    非连通图中,连通分量的生成树构成了非连通图的生成森林
    在这里插入图片描述

  1. 边的权:在一个图中,每条边都可以标上具有某种含义的数值,该数值称为该边的权值
  2. 带权图/网:边上带有权值的图称为带权图,也称
  3. 带权路径长度:一条路径上所有边的权值之和
  1. 无向完全图
    无向图中任意两个顶点之间都存在边
    ( 若无向图的顶点数|V|=n,则|E| ∈ [0,𝐶n2]=[0,n(n–1)/2] )
    在这里插入图片描述
  2. 有向完全图
    有向图中任意两个顶点之间都存在方向相反的两条弧
    ( 若有向图的顶点数|V|=n,则|E| ∈ [0,2𝐶n2]=[0,n(n–1)] )
    在这里插入图片描述

在这里插入图片描述
4.
在这里插入图片描述

一、 图的存储及其操作

邻接矩阵法

邻接矩阵法

  1. 一维数组存储顶点的信息
  2. 二维数组(邻接矩阵)存储图中边的信息

在这里插入图片描述在这里插入图片描述

在这里插入图片描述

这里是引用

  1. 第i个结点的出度=第i行的非零个数
  2. 第i个结点的入度=第i列的非零元素个数
  3. 第三个结点的=第i行、第i列的非零元素个数

邻接矩阵法存带权图(网)

在这里插入图片描述

在这里插入图片描述

邻接矩阵法的性能分析

  1. 空间复杂度:O(|V|2) 只和顶点数相关,和实际的边数无关,适用于存储稠密图
  2. 无向图的邻接矩阵是对称矩阵,可以压缩存储(只存储上三角区/下三角区)
  3. An 的元素An[i][j]等于由顶点i到顶点j的长度为n的路径的数目在这里插入图片描述
  4. 表示方式唯一。

邻接表法

顺序+链式存储
(类似树的孩子表示法)
在这里插入图片描述
在这里插入图片描述

//“边/弧”
typedef struct ArcNode{
	int adjvex;//边/弧指向哪个顶点
	struct ArcNode *next;//指向下一条弧的指针
	//InfoType. info; / /边权值
}
//“顶点”
typedef struct VNode{
	VertexType data;//顶点信息
	ArcNode *first;//第一条边/弧
}VNode,AdjList[MaxVertexNum];
typedef struct {
	AdjList vertices;//邻接表
	int vernum,arcnum;//顶点数和弧数
}

存储无向图

  1. 边结点数量:2|E|,整体空间复杂度:O( |V|+2|E| )
  2. 度:结点5的度为:2(边链表存地即为结点5相邻的边)在这里插入图片描述
    存储有向图
  3. 边结点数量:|E|,整体空间复杂度:O( |V|+|E| )
  4. 出度:结点5的出度为:2
    入度:遍历所有边链表在这里插入图片描述

总结

在这里插入图片描述

十字链表法

只能存储有向图

十字链表法是有向图的一种链式存储结构

十字链表法压缩矩阵的存储
在这里插入图片描述

存有向图
在这里插入图片描述在这里插入图片描述图的十字链表法表示不唯一,但一个十字链表法只能表示确定一个图。

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

邻接多重表

只能存无向图
无向图的另一种链式存储结构
在这里插入图片描述空间复杂度:O(|E|+|V|)

总结

在这里插入图片描述

图的基本操作

  1. Adjacent(G,x,y):
    判断图G是否存在边<x, y>或(x, y)
    在这里插入图片描述

  2. Neighbors(G,x):
    列出图G中与结点x邻接的边
    在这里插入图片描述在这里插入图片描述

  3. InsertVertex(G,x):
    在图G中插入顶点x
    在这里插入图片描述

  4. DeleteVertex(G,x):
    从图G中删除顶点x
    在这里插入图片描述在这里插入图片描述

  5. AddEdge(G,x,y):
    若无向边(x, y)或有向边<x, y>不存在,则向图G中添加该边
    在这里插入图片描述

  6. RemoveEdge(G,x,y):
    若无向边(x, y)或有向边<x, y>存在,则从图G中删除该边
    在这里插入图片描述

  7. 在这里插入图片描述在这里插入图片描述
    在这里插入图片描述在这里插入图片描述

三、图的遍历

BFS广度优先遍历

队列

bool visited[MAX_VERTEX_NUM];
void BFSTraverse(Graph G){
	for(int i=0;i<G.vertextnum;i++) 
		visited[i]=false;
	InitQueue(Q);
	for(i=0;i<G.verxnum;++i){
			if(!visited[i])//每个连通分量调用依次BFS
				BFS(G,i);
	}
}
void BFS(Graph G,int v){
	visit(v);
	visited[v] = true;
	Enqueue(Q,v);//入队列
	while(!isEmpty(Q)){
		DeQueue(Q,v);//顶点v出队列
		for(w = FirstNeigbor(G,v);w>=0;w = NextNeigbor(G,v,w)){
			if(visited[w]){
				visit(w);//访问
				visited[w]=true;
				EnQueue(Q,w);
			}//if
		}//for
	}//while
}

类似树的层次遍历

  1. 同⼀个图的邻接矩阵表示⽅式唯⼀,因此⼴度优先遍历序列唯⼀
  2. 同⼀个图邻接表表示⽅式不唯⼀,因此⼴度优先遍历序列不唯⼀

BSF算法性能分析

  1. 空间复杂度:最坏情况,辅助队列⼤⼩为 O(|V|) (一个顶点和所有点相邻)
  2. 开销在于访问顶点和找邻边:
    邻接表存储方式
    在这里插入图片描述无向图:O(|V|+2|E|)
    邻接矩阵
    在这里插入图片描述

广度优先生成树

广度优先搜索过程中可以得到一颗遍历树,称广度优先搜索树

  1. 由于邻接表的表示⽅式不唯⼀,因此基于邻接表⼴度优先⽣成树也不唯⼀
  2. 邻接矩阵存储表示唯一,其广度优先生成树也是唯一
  3. 对⾮连通图的⼴度优先遍历,可得到⼴度优先⽣成森林

DFS深度优先遍历

类似树的先根遍历

bool visited[MAX_VERTEX_NUM]
void DFSTravel(Graph G){
	int v;
	for(v=0;v<G.vernum;v++) visited[v] = false;
	
	for(v=0;v<G.vernum;v++){
		if(!visited[v]) DFS(G,v);
	}
}
void DFS(Graph G,int v){
	visit(v);
	visited[v] = true;
	
	for(int w = FirstNeibor(G,v);w>=0;w = NextNeighbor(G,v,w)){
		if(!visited[w]) DFS(G,w);
	}
}

对于同一个图:

  1. 基于邻接矩阵的遍历得到的DFS序列和BFS序列是唯一的。
  2. 基于邻接表的遍历得到的DFS序列和BFS序列是不唯一的。

复杂度分析

  1. 空间复杂度
    在这里插入图片描述
  2. 时间复杂度 = 访问各结点所需时间+探索各条边所需时间
  1. 邻接矩阵
    在这里插入图片描述
  2. 邻接表
    在这里插入图片描述

深度优先搜索树

对连通图调用DFS才会产生深度优先生成树
否则生成深度优先生成森林
基于邻接表存储的生成树不唯一

图的遍历和图的连通性

  1. 对⽆向图进⾏BFS/DFS遍历调⽤BFS/DFS函数的次数=连通分量数
    在这里插入图片描述
  2. 对有向图进⾏BFS/DFS遍历调⽤BFS/DFS函数的次数要具体问题·具体分析`
    在这里插入图片描述

最小生成树

连通图生成树包含图中全部顶点的一个极小连通子图
在这里插入图片描述

最小生成树(最小代价树)

性质:

  1. 最小生成树不唯一;
  2. 最小生成树的边的权值之和总是唯一的
  3. 最小生成树的边数为顶点数-1
    在这里插入图片描述

Prim和Kruskal都基于贪心算法

Prim算法

寻找与当前生成树最近的结点
在这里插入图片描述

  1. 在这里插入图片描述
  2. 在这里插入图片描述
  3. 在这里插入图片描述
  4. 在这里插入图片描述
  5. 在这里插入图片描述
  6. 在这里插入图片描述
  7. 在这里插入图片描述

Kruskal算法

每次选择一条权值最小的边
在这里插入图片描述

  1. 在这里插入图片描述
  2. 在这里插入图片描述
  3. 在这里插入图片描述
  4. 在这里插入图片描述
  5. 在这里插入图片描述

时间复杂度分析

  1. Prim算法:O(|V|2)
    适用于边稠密图
  2. Kruskal算法:O(|E|log2|E|)
    适用于边稀疏图

思想

Prim
1.
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
松弛算法,更新其他未加入树的结点到新结点的距离在这里插入图片描述
2.
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
3.
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
时间复杂度分析:
从V 0 开始,总共需要 n-1 轮处理(加入n-1个顶点) O(n-1)
每⼀轮处理:循环遍历所有个结点,找到lowCost最低的,且还没加⼊树的顶点。O(n)
再次循环遍历,更新还没加⼊的各个顶点的lowCost值 O(n)
总时间复杂度:O[(n-1)*2n]=O(|V|2)

Kruskal算法:
0.
在这里插入图片描述
1.
在这里插入图片描述
在这里插入图片描述
2.
在这里插入图片描述
在这里插入图片描述
3.
在这里插入图片描述
在这里插入图片描述
4.
在这里插入图片描述
5.
在这里插入图片描述
时间复杂度分析
共执行e轮,每轮判断两个顶点是否属于同⼀集合,需要 O(log 2 e)
总时间复杂度 O(elog2e)

最短路径

BFS算法(无权图)

void Best_Min_BFS(Graph G,int v){
	d[i] = ∞;//距离
	path[i] = -1;//前驱
	
	d[v] = 0;
	vis[v] = true;
	EnQueue(v);
	while(!isEmpty(Q)){
		DeQueue(Q,v);
		for(w = FirstNeigbor(G,v);w>=0;w = NextNeigbor(G,v,w)){
			if(!vis[w]){
				vis[w] = true;
				d[w] = d[v]+1;
				path[w] = v;
				EnQueue(w);
			}//if
		}
	}
}

Dijkstra算法

①、初始化 →②、FindMin→③、松弛→④是否还有结点(回到2)

在这里插入图片描述
1.
在这里插入图片描述
在这里插入图片描述
松弛算法在这里插入图片描述
在这里插入图片描述
2.
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
3.
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
4.
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
时间复杂度:==O(n2)==既O(|V|2)
Dijkstra 算法不适⽤于有负权值的带权图

Floyd算法

可解决带“负权图”,不能解决带负权回路图

在这里插入图片描述

for(int k = 0;k<n;k++){
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			if(A[i][j]>A[i][k]+A[k][j]){
				A[i][j] = A[i][k]+A[k][j];
				path[i][j] = k;
			}
		}
	}
}

时间复杂度:O(n3)

总结

在这里插入图片描述

有向无环图

有向⽆环图:若⼀个有向图不存在环,则称为有向⽆环图,简称DAG图

DGA描述表达式

用有向无环图表示可以实现对相同子式的共享,从而节约存储空间
在这里插入图片描述
在这里插入图片描述

解题方法:
1.
在这里插入图片描述
2.
在这里插入图片描述
3. 在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
4.
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

拓扑排序

AOV网:⽤==DAG图(有向⽆环图)==表示⼀个⼯程。
顶点表示活动,有向边<V i , V j >表示活动V i 必须先于活动V j 进⾏
在这里插入图片描述
AOV网不存在回路

拓扑排序:找到做事的先后顺序
每个AOV⽹都有⼀个或多个拓扑排序序列。

在这里插入图片描述

bool TopoLogicalSort(Graph G){
	InitStack(S);
	for(int i=0;i<G.vexnum;i++){
		if(indgree[i]==0) Push(S,i);//将所有入度为0的顶点进栈

	}
	
	int count = 0;
	while(!S.isEmpty()){
		Pop(S,i);
		print[count++]=i;//输出顶点i
		for(p=G.vertices[i].firstarc;p!=NULL;p=p->nextarc){
		//将所有i指向的顶点的入度减1,并且将入度减为0的顶点压入栈S
			v = p->adjvex;//指向的顶点
			if((--indegree[v])==0) Push(S,v);//入度为0,入栈
		}//while
	if(count<G.vernum) return false;//排序失败,有向图中有回路
	return true;
	}
}

在这里插入图片描述时间复杂度:O(|V|+|E|)

在这里插入图片描述
邻接矩阵是三角矩阵,则存在拓扑序列。反之未必

逆拓扑排序

在这里插入图片描述在这里插入图片描述

在这里插入图片描述

DSF实现逆拓扑排序

在这里插入图片描述
在这里插入图片描述

关键路径

AOE网
在带权有向图中,以顶点表示事件,以有向边表示活动,以边上的权值表示完成该活动的开销(如完成活动所需的时间),称之为⽤边表示活动的⽹络,简称AOE⽹
在这里插入图片描述
性质
① 只有在某顶点所代表的事件发⽣后,从该顶点出发的各有向边所代表的活动才能开始;
② 只有在进⼊某顶点的各有向边所代表的活动都已结束时,该顶点所代表的事件才能发⽣。
另外,有些活动是可以并⾏进⾏的

在这里插入图片描述
在这里插入图片描述

关键路径

从源点到汇点的有向路径可能有多条,所有路径中,具有最⼤路径⻓度的路径称为关键路径,⽽把关键路径上的活动称为关键活动
在这里插入图片描述
在这里插入图片描述

  1. 事件vk最早发生时间ve(k)
    在这里插入图片描述

ve(源点) = 0
2. 活动ai最早开始时间e(i)
在这里插入图片描述
3. 事件vk的最迟发生时间vl(k)
在这里插入图片描述
4. 活动ai的最迟开始时间l(i)
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值