当前位置: 首页 > news >正文

图论理论基础(1)

文章目录

  • 图论理论基础(1)
    • 1. 图的基本概念
      • 1.1 基本术语
    • 2. 图的分类
      • 2.1 有向图 vs 无向图
      • 2.2 加权图 vs 无权图
      • 2.3 度(Degree)
    • 3. 图的连通性
      • 3.1 连通图 vs 非连通图
      • 3.2 强连通性(有向图)
      • 3.3 连通分量(无向图)
    • 4. 图的存储方式
      • 4.1 邻接矩阵
      • 4.2 邻接表
      • 4.3 边列表
    • 5. 图的遍历算法
      • 5.1 深度优先搜索(DFS)
      • 5.2 广度优先搜索(BFS)
    • 6. 图论算法分类
      • 6.1 图的存储与遍历
      • 6.2 拓扑排序
      • 6.3 并查集
      • 6.4 最短路径算法
      • 6.5 最小生成树
    • 7. 时间复杂度总结
    • 8. DFS与BFS对比
      • 8.1 算法对比
      • 8.2 DFS搜索过程
      • 8.3 DFS代码框架
    • 9. BFS详解
      • 9.1 BFS使用场景
      • 9.2 BFS搜索过程
      • 9.3 BFS代码框架

图论理论基础(1)

1. 图的基本概念

**图(Graph)**是由顶点(Vertex/Node)和边(Edge)组成的数据结构,用来表示事物之间的关系。

1.1 基本术语

  • 顶点(Vertex):图中的节点,表示事物
  • 边(Edge):连接两个顶点的线,表示关系
  • 路径(Path):从一个顶点到另一个顶点经过的边的序列
  • 环(Cycle):起点和终点相同的路径

2. 图的分类

2.1 有向图 vs 无向图

  • 无向图:边没有方向,A-B 和 B-A 是同一条边
  • 有向图:边有方向,A→B 和 B→A 是不同的边

2.2 加权图 vs 无权图

  • 无权图:边没有权重,只表示连接关系
  • 加权图:边有权重,表示距离、成本等

2.3 度(Degree)

  • :与顶点相连的边的数量
  • 出度:有向图中从顶点出发的边的数量
  • 入度:有向图中指向顶点的边的数量

3. 图的连通性

3.1 连通图 vs 非连通图

  • 连通图:任意两个顶点之间都存在路径
  • 非连通图:存在两个顶点之间没有路径

3.2 强连通性(有向图)

  • 强连通图:任意两个顶点之间都存在双向路径
  • 强连通分量:极大强连通子图

示例

有向图:A → B → C → A↓D强连通分量1:{A, B, C} - 这三个节点互相可达
强连通分量2:{D} - 单独一个节点

图解

A ──→ B ──→ C
│           │
│           │
└───────────┘
│
↓
D

3.3 连通分量(无向图)

  • 连通分量:无向图中的极大连通子图
  • 连通分量数量:图中连通分量的个数

示例

无向图:A-B-C, D-E, F连通分量1:{A, B, C} - 这三个节点互相连通
连通分量2:{D, E} - 这两个节点互相连通  
连通分量3:{F} - 单独一个节点
连通分量数量:3

图解

A ── B ── C    D ── E    F

4. 图的存储方式

4.1 邻接矩阵

// 适合稠密图,空间复杂度O(V²)
vector<vector<int>> graph(V, vector<int>(V, 0));
// graph[i][j] = 1 表示顶点i和j之间有边

4.2 邻接表

// 适合稀疏图,空间复杂度O(V+E)
vector<vector<int>> graph(V);
// graph[i] 存储与顶点i相邻的所有顶点

4.3 边列表

// 存储所有边的信息
vector<pair<int, int>> edges;  // 无权边
vector<tuple<int, int, int>> edges;  // 加权边 (u, v, weight)

5. 图的遍历算法

5.1 深度优先搜索(DFS)

算法特点

  • 深度优先:尽可能深地搜索图的分支
  • 递归实现:使用递归栈,代码简洁
  • 应用场景:路径查找、连通性判断、拓扑排序
  • 时间复杂度:O(V+E),每个顶点和边访问一次
  • 空间复杂度:O(V),递归栈的深度

执行过程示例

图:A-B-C|   |D   EDFS访问顺序:A → B → C → E → D

代码实现

void dfs(int node, vector<bool>& visited, vector<vector<int>>& graph) {visited[node] = true;  // 标记当前节点已访问// 遍历当前节点的所有邻居for (int neighbor : graph[node]) {if (!visited[neighbor]) {  // 如果邻居未被访问dfs(neighbor, visited, graph);  // 递归访问邻居}}
}

5.2 广度优先搜索(BFS)

算法特点

  • 广度优先:逐层访问,先访问距离近的节点
  • 队列实现:使用队列维护访问顺序
  • 应用场景:最短路径、层次遍历、连通性判断
  • 时间复杂度:O(V+E),每个顶点和边访问一次
  • 空间复杂度:O(V),队列的最大长度

执行过程示例

图:A-B-C|   |D   EBFS访问顺序:A → B → D → C → E
层次:第0层:A第1层:B, D第2层:C, E

代码实现

void bfs(int start, vector<vector<int>>& graph) {queue<int> q;  // 队列存储待访问的节点vector<bool> visited(graph.size(), false);  // 标记数组q.push(start);  // 将起始节点加入队列visited[start] = true;  // 标记起始节点已访问while (!q.empty()) {  // 队列不为空时继续int node = q.front();  // 取出队首节点q.pop();  // 从队列中移除// 遍历当前节点的所有邻居for (int neighbor : graph[node]) {if (!visited[neighbor]) {  // 如果邻居未被访问visited[neighbor] = true;  // 标记邻居已访问q.push(neighbor);  // 将邻居加入队列}}}
}

6. 图论算法分类

6.1 图的存储与遍历

  • DFS/BFS:基础遍历算法
  • 应用:岛屿数量、被围绕的区域

6.2 拓扑排序

  • Kahn算法:基于入度的拓扑排序
  • DFS法:基于深度优先搜索的拓扑排序
  • 应用:课程表、任务调度

6.3 并查集

  • Union-Find:集合合并与查询
  • 应用:省份数量、朋友圈

6.4 最短路径算法

  • Dijkstra:单源最短路径(非负权)
  • Bellman-Ford:单源最短路径(可处理负权)
  • Floyd-Warshall:多源最短路径

6.5 最小生成树

  • Kruskal:基于边的贪心算法
  • Prim:基于顶点的贪心算法

7. 时间复杂度总结

算法时间复杂度空间复杂度适用场景
DFS/BFSO(V+E)O(V)图遍历
拓扑排序O(V+E)O(V)DAG排序
并查集O(α(n))O(V)连通性判断
DijkstraO((V+E)logV)O(V)单源最短路
FloydO(V³)O(V²)多源最短路
KruskalO(ElogE)O(V)最小生成树

8. DFS与BFS对比

8.1 算法对比

比较项DFS(深度优先搜索)BFS(广度优先搜索)
搜索策略一条路走到黑(递归/栈)一层一层扩展(队列)
实现方式通常用 递归显式栈通常用 队列(queue)
适用场景适合 全路径搜索、组合问题、回溯问题(如图遍历、排列组合)适合 最短路径问题、层次遍历(如最短步数、层数搜索)
空间复杂度相对较小(与递归深度有关)相对较大(需存整层节点)
典型应用迷宫求解、图连通分量、全排列最短路径、最少步数、层序遍历

8.2 DFS搜索过程

假设你在一个迷宫中:

  1. 看到一个路口 → 选一条路走;
  2. 走到底发现死路 → 返回上一个岔口;
  3. 选另一条没走过的路 → 再次深入;
  4. 最终找到所有可能的出口。

这整个过程就叫 深度优先搜索(DFS)

8.3 DFS代码框架

vector<vector<int>> result; // 保存符合条件的所有路径
vector<int> path; // 起点到终点的路径void dfs (参数){if (终止条件) {存放结果;return;}for (选择:本节点所连接的其他节点) {处理节点;dfs(图,选择的节点); // 递归回溯,撤销处理结果}
}

9. BFS详解

9.1 BFS使用场景

广度优先搜索(Breadth First Search,简称 BFS)是一种逐层搜索的算法,常用于在图或树结构中寻找最短路径或最小步数的问题。

常见使用场景:

  1. 最短路径问题
    例如在无权图中,寻找从起点到终点的最短路径。
    • 典型例题:二叉树的最短深度、迷宫最短路径、网络中最短连接。
  2. 层序遍历
    BFS 天然按层扩展节点,因此在树结构中可用于层序遍历。
  3. 状态搜索类问题
    如八数码问题、单词接龙、棋盘问题等,BFS 可用于寻找最少操作次数。
  4. 网络流与最短增广路
    在最大流算法(如 Edmonds-Karp)中,BFS 用于寻找最短增广路径。
  5. 多源最短路问题
    同时从多个起点出发,计算所有点到最近起点的最短距离。

9.2 BFS搜索过程

BFS 采用队列(queue)实现“先进先出”的搜索逻辑,从起点开始,依次访问相邻节点,逐层向外扩展。

搜索流程:

  1. 将起点加入队列,并标记为已访问;
  2. 当队列非空时:
    • 取出队首节点;
    • 遍历该节点的所有邻接节点;
    • 若邻接节点未访问,则加入队列并标记;
  3. 直到队列为空或找到目标。

9.3 BFS代码框架

int dir[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}
};// 表示四个方向
// grid 是地图,也就是一个二维数组
// visited标记访问过的节点,不要重复访问
// x,y 表示开始搜索节点的下标
void bfs(vector<vector<char>>& grid, vector<vector<bool>>& visited, int x, int y) {queue<pair<int, int>> que; // 定义队列que.push({x, y}); // 起始节点加入队列visited[x][y] = true; // 只要加入队列,立刻标记为访问过的节点//加入队列就代表 走过,就需要标记,而不是从队列拿出来的时候再去标记走过。要不然会导致很多重复while(!que.empty()) { // 开始遍历队列里的元素pair<int ,int> cur = que.front(); que.pop(); // 从队列取元素int curx = cur.first;int cury = cur.second; // 当前节点坐标for (int i = 0; i < 4; i++) { // 开始想当前节点的四个方向左右上下去遍历int nextx = curx + dir[i][0];int nexty = cury + dir[i][1]; // 获取周边四个方向的坐标if (nextx < 0 || nextx >= grid.size() || nexty < 0 || nexty >= grid[0].size()) continue;  // 坐标越界了,直接跳过if (!visited[nextx][nexty]) { // 如果节点没被访问过que.push({nextx, nexty});  // 队列添加该节点为下一轮要遍历的节点visited[nextx][nexty] = true; // 只要加入队列立刻标记,避免重复访问}}}}
http://www.dtcms.com/a/519453.html

相关文章:

  • 开源 Linux 服务器与中间件(十)Mqtt协议和Emqx服务器安装测试
  • 网站建设实践鉴定手机网站建设讯息
  • 网站管理文档怎么写晚上睡不着看点害羞的东西app
  • uni-app 广告弹窗最佳实践:不扰民、可控制频次、含完整源码
  • 使用eNSP模拟器搭建网络拓扑结构(笔记2):从 0 到 1 掌握华为网络仿真
  • UniApp 多页面编译优化:编译时间从10分钟到1分钟
  • C++变量与函数命名规范技术指南 (基于华为编码规范与现代C++最佳实践)
  • ELK1——elasticsearch
  • 【图像卷积基础】卷积过程卷积实现通道扩充与压缩池化Pooling原理和可视化
  • 杭州公司网站设计外贸手工做兼职的网站
  • 深入浅出Langchain4j——构建Java大语言模型应用的新范式
  • Babylon.js学习之路《添加自定义摇杆控制相机》
  • 【JAVA 进阶】SpringBoot集成Sa-Token权限校验框架深度解析
  • 【CMakeLists.txt】Qt6 依赖配置详解
  • 用js做网站登录网页成品
  • 数据库安全网关:从“看得见访问”到“控得住风险”的关键一层
  • 对泊松过程的理解
  • 【数论】质数筛(埃氏筛、欧拉筛)
  • 扩展名网站兰州做网站一咨询兰州做网站公司
  • 华为OD-Java面经-21届考研
  • Excel拆分和合并优化版本
  • 智能网联汽车:当汽车遇上“智慧网络”
  • 常规点光源在工业视觉检测上的应用
  • C++新特性——正则表达式
  • 基于卷积神经网络的汽车类型识别系统,resnet50,vgg16,resnet34【pytorch框架,python代码】
  • 设计 企业网站电脑系统网站建设
  • 做网站业务的怎么找资源网站推广名片
  • FPGA强化- HDMI显示器驱动设计与验证
  • 【PPT-ungroup PPT解组合,python无水印】
  • Java 17 环境下 EasyPoi 反射访问异常分析与解决方案(ExcelImportUtil.importExcelMore)