【算法笔记】图论基础(一):建图、存图、树和图的遍历、拓扑排序、最小生成树
目录
- 何为图论
- 图的概念
- 图的一些基本概念
- 有向图和无向图
- 带权图
- 连通图和非连通图
- 对于无向图
- 对于有向图
- 度
- 对于无向图
- 对于有向图
- 一些结论
- 环
- 自环、重边、简单图、完全图
- 自环
- 重边
- 简单图
- 稀疏图和稠密图
- 子图、生成子图
- 同构
- 图的存储
- 直接存边
- 邻接矩阵存边
- 邻接表存边
- 链式前向星存边
- 图的遍历
- 树和图的遍历(图示)
- 树
- 图
- 树和图的深度优先遍历(dfs)
- 树和图的广度优先遍历(bfs)
- 拓扑排序
- 什么是拓扑排序?
- 结论
- 例题
- 一个技巧
- 最小生成树
- Kruskal求最小生成树
- 算法过程
- 图示
- 例题
- Prim求最小生成树
- 算法过程
- 图示
- 例题
- 最大生成树
何为图论
图的概念
图(Graph) 是一种数据结构,是由 节点(Node) 和 边(Edge) 组成的集合。
由节点所构成的集合就叫点集,由边所构成的集合就叫边集,点集和边集放在一起就形成了一张图。
注意:一张图的边集可以为空,但点集一定不能为空。
下面就是一个图,可以看到这个图有5个顶点,分别编号为{0,1,2,3,4}。同时这个图有5条边,例如,在顶点1和顶点3之间存在着一条边。
在图这个数据结构上面的所有问题和算法,统称为图论。
图的一些基本概念
有向图和无向图
图的边分为有向边和无向边,只有有向边的图就是有向图,只有无向边的图就是无向图。
上面的图片就是一个无向图,而如果把图改成这样,就是有向图。
如果对于边a -> b,a能到b、b不能到a,那这就是一条a到b的有向边。
如果对于边a – b,a能到b、b也能到a,那这就是一条a到b的无向边。
可以发现一个结论:无向边就是特殊的有向边、无向图就是特殊的有向图
解释:对于两个点a, b,你想在a、b之间连一条无向边,只需从a向b连一条有向边,再从b到a连一条有向边即可,就像下面这样:
所以我们研究的所有问题,只需考虑有向图即可,无向图只需在建图的时候建两条相反的有向边。
带权图
对于一个图,如果每一条边都被赋予一个数作为该边的权,这个图就是带权图。
边权其实也就是边长
比如下图
边权为正数的边就是正权边,比如上图中的(0, 1)、(2, 4)
边权为负数的边就是负权边,比如上图中的(1, 2)、(1, 3)
- 对于非带权图,表示的通常是节点和节点之间的连通关系
- 对于带权图,表示的同通常是节点和节点的距离
连通图和非连通图
对于无向图
对于无向图中的两个点u,v,如果存在一条从u到v的路径,则称为u和v连通。
连通图
非连通图
如果无向图的任意两个顶点均连通,这个图就是连通图,图的这一性质被称为连通性。
对于有向图
对于有向图中的两个点u,v,如果存在一条从u到v的路径,则称为u可达v。
若一张有向图的节点两两互相可达,则称这张图是强连通的
若一张有向图的边替换为无向边后可以得到一张连通图,则称原来这张有向图是弱连通的
弱连通图
强连通图
度
顶点连接的边数叫做这个顶点的度
对于无向图
- 无向图中一个点的度数就是这个点的临边数。
比如下面的无向图,d(0) = 2, d(1) = 3, d(4) = 1…
对于有向图
有向图的度数分为两种:入度和出度
对于无向图中的一个点,
- 它的入度等于一这个点为终点的边(即直接指向这个点的边)的数量
- 它的出度等于以这个点为起点的边(即从这个点指向别的点的边)的数量
比如下面的有向图,din(0) = 0,dout(0) = 2, din(1) = 1, dout(1) = 2, din(4) = 1, dout(4) = 0…
一些结论
1.在任意无向图中,所有节点的度数和等于总边数*2。
2. 在任意无向图中,度为奇数的顶点的个数为偶数。
3. 在任意有向图中,所有节点入度的和等于所有节点出度的和。
环
图中起点和终点重合的非空路径叫做环
比如下面的图中,0 -> 1 -> 2 -> 0这条路径就是一个环
没有环的图叫无环图,没有环的有向图叫有向无环图,没有环的连通图称为树。
自环、重边、简单图、完全图
自环
对于图中的一条边(u, v),如果u == v,那么这条边就被称做自环。
比如下图中的(2, 2)就是一个自环。
重边
如果图中有两条完全相同的边(起点、终点、方向都相同),那么他们就被称为一组重边。
比如下图中,(2, 4)和(2, 4)就是一组重边,但(0, 1) 和(1, 0)不是。
简单图
没有重边和自环的图被称作简单图。
任意两个节点都相邻的无向简单图被称为完全图。
若有向图满足任意不同两点间都有两条方向不同的边,则称为有向完全图。
稀疏图和稠密图
- 若一张图的边数远小于其点数的平方,那么它是一张 稀疏图 。
- 若一张图的边数接近其点数的平方,那么它是一张 稠密图 。
稀疏图和稠密图一般来讨论时间复杂度为 O ( V 2 ) O(V^2) O(V2)的算法和 O ( E ) O(E) O(E)的算法的效率差异,在稠密图上二者效率相当,在稀疏图上 O ( E ) O(E) O(E)的算法更优。
子图、生成子图
如果图a的节点集和边集分别是图b的节点集的子集和边集的子集,那么就称图a为图b的子图。
含有图G的所有顶点的子图称为图G的生成子图
如果一个生成子图是树(无环连通图),那么就称这个生成子图为生成树
比如下面这张图,就是上面那个出现很多次的无向图的一个生成树
同构
定义(图的同构)
给定两个图 G G G 和 H H H。若存在一个函数 f : V ( G ) → V ( H ) f: V(G) \to V(H) f:V(G)→V(H)满足对于任意顶点 u , v u, v u,v, ( u , v ) ∈ E ( G ) (u, v) \in E(G) (u,v)∈E(G) 当且仅当 ( f ( u ) , f ( v ) ) ∈ E ( H ) (f(u), f(v)) \in E(H) (f(u),f(v))∈E(H), 则称 f f f 为从 G G G 到 H H H 的一个同构,并且称图 G G G 与 H H H 是同构的,记作 G ≃ H G \simeq H G≃H
通俗的来讲,两个图同构就是结构相同,比如下面两个图就是同构的
图的存储
算法竞赛中,你想做图论的题,肯定得先学会怎么存图,图的存储主要分为以下几种方式:
直接存边
最简单粗暴的一种,用一个结构体数组直接存边
struct Edge{int a, b, w; // 表示一条 a->b 的边,边权为w
}edges[N];for(int i = 0; i < m; i++){ // 输入m条边int a, b, w;cin >> a >> b >> w;edges[i] = {a, b, w};
}
需要遍历所有边、做给边排序(比如Kruskal算法)等操作的时候常用这种存图方法。
邻接矩阵存边
邻接矩阵就是用一个二维数组来存边,数组的下标就是边的端点,数组的值就是边的权值。
对于不带权的图, g [ a ] [ b ] = 1 g[a][b] = 1 g[a][b]=1表示存在从a到b的边, g [ a ] [ b ] = 0 g[a][b] = 0 g[a][b]=0表示不存在,这时的邻接矩阵也叫可达性矩阵。
int g[N][N];while(m--){ // 输入m条边int a, b;cin >> a >> b;g[a][b] = 1;
}
对于带权图, g [ a ] [ b ] = w g[a][b] = w g[a][b]=w表示存在从a到b、权值为w的边, g [ a ] [ b ] = 0 g[a][b] = 0 g[a][b]=0表示不存在边
int g[N][N];while(m--){ // 输入m条边int a, b, w;cin >> a >> b >> w;g[a][b] = w;
}
邻接矩阵常用于稠密图,并且邻接矩阵只能用于没有重边或重边可以忽略的情况(比如求最短路时,如果有重边就只要最短的一条就可以了,其他的都可以忽略)。
邻接表存边
使用一个支持动态增加元素的数据结构构成的数组,如vector来存边。g[a]记录a的所有出边的信息(如终点、边权等)。
对于不带权的图,g[a]存的是所有以a为起点的边的终点。
vector<int> g[N];for(int i = 0; i < m; i++){int a, b;cin >> a >> b;g[a].push_back(b);
}for(int v : g[u]){ // 遍历u的所有出边,v就是出边的终点}
对于带权图,g[a]存的是所有以a为起点的边的终点和边权。
typedef pair<int, int> PII;
vector<PII> g[N];for(int i = 0; i < m; i++){int a, b, w;cin >> a >> b >> w;g[a].push_back({b, w});
}for(auto i : g[u]){ // 遍历u的所有出边int v = i.first, w = i.second; // v:出边的终点,w:边权
}
这是最常用的一种存边方法,存各种图都很适合。
链式前向星存边
链式前向星存图其实就是用单链表实现的的邻接表。
想用的话先去学链表,在这不做过多介绍。
int h[N], e[N], ne[N], idx;void add(int a, int b){e[idx] = b, ne[idx] = h[a], h[a] = idx++; // add(a, b) : 加一条 a->b的边
}memset(h, -1, sizeof h); // 表头初始化成-1
idx = 0;for(int i = h[t]; i != -1; i = ne[i]){ // 遍历t的出边int j = e[i]; // j是出边的终点
}
int h[N], e[N], ne[N], w[N], idx;void add(int a, int b, int c){e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++; // add(a, b, c) : 加一条 a->b 边权为c的边
}memset(h, -1, sizeof h); // 表头初始化成-1
idx = 0;for(int i = h[t]; i != -1; i = ne[i]){ // 遍历t的出边int j = e[i]; // j是出边的终点
}
存各种图都很适合,但不能快速查询一条边是否存在,也不能方便地对一个点的出边进行排序。
优点是边是带编号的,有时会非常有用,而且如果 cnt 的初始值为奇数,存双向边时 i ^ 1即是 i 的反边
图的遍历
树和图的遍历(图示)
树
dfs遍历顺序:1, 2, 5, 9, (5), 10, (5), (2), (1), 3, 6, 11,(6), (3), 7, (3), (1), 4, 8
bfs遍历顺序:1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
图
dfs遍历顺序:1, 2, 5, 7, 6,(7),(5),(2),(1), 3, (1), 4
bfs遍历顺序:1, 2, 3, 4, 5, 6, 7
树和图的深度优先遍历(dfs)
和传统树的遍历一样,图的遍历也是一条路走到黑、不撞南墙不回头
给他一个遍历的起点,他会先走该点的第一条出边,然后再遍历终点的第一条出边…直到遍历到某个点没有出边了,再回溯去遍历第二条出边。
bool st[N];void dfs(int u){st[u] = true;...;for(int v : g[u]){if(st[v]) continue;dfs(v);...;}...;
}dfs(1);
树和图的广度优先遍历(bfs)
给他一个遍历的起点,他会把这个点所有的出边都走完,然后再去走所有第一步到的终点的所有出边…直到队首的点没有出边可走(队列为空,所有点就都遍历完了)
bool st[N];void bfs(int start){queue<int> q;q.push(start);st[start] = true;while(!q.empty()){int u = q.front();q.pop();...;for(int v : g[u]){if(st[v]) continue;q.push(v);st[v] = true;...;}}
}bfs(1);
拓扑排序
什么是拓扑排序?
一个有向图,如果图中有入度为 0 的点,就把这个点删掉,同时也删掉这个点所连的边。
一直进行上面的处理,如果所有点都能被删掉,则这个图可以进行拓扑排序。
结论
一个图可以拓扑排序 ⇔ \Leftrightarrow ⇔这个图是有向无环图(DAG)
例题
848. 有向图的拓扑序列
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <queue>
#define endl '\n'
using namespace std;
const int N = 1e5 + 10;
int n, m;
vector<int> g[N]; // 邻接表存边
int d[N]; // 存每个点的入度
int res[N]; // 存拓扑序列(答案)bool topsort(){int cnt = 0; // 记录当前删掉的节点数,也就是当前拓扑序列中的节点数queue<int> q;for(int i = 1; i <= n; i++){if(!d[i]) q.push(i); // 先把入度为0的点入队}while(!q.empty()){int t = q.front();q.pop();res[cnt++] = t; // 记录答案for(int i : g[t]){ // 遍历i的每条出边,给每个临点的入度-1(拿掉一条边)if(--d[i] == 0) q.push(i); // 将新的入度为0的点入队}}return cnt == n; // 如果每个点都能被删掉,就说明是有向无环图
}int main(){ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);cin >> n >> m;while(m--){int a, b;cin >> a >> b;g[a].push_back(b); // 边 a->bd[b]++; // b入度+1}if(!topsort()) cout << -1 << endl;else{for(int i = 0; i < n; i++) cout << res[i] << ' ';}cout << endl;return 0;
}
一个技巧
一个有向无环图的拓扑序列是有很多种的,如果按上面的写法,就是先把所有入度为0的节点删除,再去删除其后继结点,但如果题目中要求优先输出编号大的或编号小的,把 q u e u e queue queue换成 p r i o r i t y _ q u e u e priority\_queue priority_queue就好了,维护一个大根堆(编号大的先输出)/小根堆(编号小的先输出),其他代码都一样。
例如:确定比赛名次
最小生成树
首先,如果一个生成子图是树(无环连通图),那么就称这个生成子图为生成树
一个无向图有很多的生成树,规定边权和最小的一个叫做最小生成树。
求最小生成树有两种最简单常用的算法,Kruskal算法和Prim算法,两种算法都是基于贪心的思想。
Kruskal求最小生成树
Kruskal算法非常好理解,简单粗暴,他是一个向图中加边的过程。
算法过程
- 将所有的边都拿掉,只留下所有的点,并将边按边权从小到大排序。
- 从小到大遍历每条边,看加上这条边会不会形成环,如果这个边与之前选择的所有边不会组成环,就选择这条边,将边权加到答案,反之,舍去。
- 遍历完所有边后,筛选出来的边和所有的顶点构成此图的最小生成树。
判断是否会产生回路的方法为:使用并查集。
- 在初始状态下给各个顶点在不同的集合中。
- 遍历过程的每条边,判断这两个顶点的是否在一个集合中
- 如果边上的这两个顶点在一个集合中,说明两个顶点已经连通,再加边就会成环,这条边不要。如果不在一个集合中,则要这条边。
图示
例题
Kruskal算法求最小生成树
#include <iostream>
#include <algorithm>
#include <cstring>
#define endl \n'
using namespace std;
const int N = 2e5 + 10;
int n, m;
int fa[N];struct Edge{int a, b, w; // 结构体数组存边
} edges[N];bool cmp(Edge a,Edge b){return a.w < b.w; // 按边权从小到大排序
}int find(int x){if(fa[x] != x)fa[x] = find(fa[x]);return fa[x];
}int kruskal(){sort(edges, edges + m, cmp); // 按边权从小到大排序for(int i = 1; i <= n; i++) fa[i] = i; // 并查集初始化int res = 0, cnt = 0; // res记录当前加到最小生成树中的边的权值的总和, cnt记录当前加了多少条边for(int i = 0; i < m; i++){int a = edges[i].a, b = edges[i].b, w = edges[i].w;a = find(a), b = find(b); // 并查集找祖先if(a != b){ // 如果a和b不在一个集合里,加边就不会成环fa[a] = b; // 加这条边res += w; // 将边权累加cnt++; // 又加进去一条边}}if(cnt < n - 1)return -1; // 加不到n - 1条边说明图不连通return res;
}int main(){ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);cin >> n >> m;for (int i = 0; i < m; i++){int a, b, w;cin >> a >> b >> w;edges[i] = {a, b, w}; // m条边}int t = kruskal();if(t == -1) cout << "impossible" << endl;else cout << t << endl;return 0;
}
Prim求最小生成树
Prim算法是向图中加点的过程,他是维护了两个集合:{已经加到最小生成树中的点和边}(连通部分) 和 {还未加到最小生成树中的点和边},每次将离连通部分的最近的点和点对应的边加入连通部分,连通部分逐渐扩大,最后将整个图连通起来,并且边长之和最小,最后的连通部分就是该图的最小生成树。
算法过程
- 一开始,任取一个起点加入连通部分(第一次迭代)
- 接下来每次迭代,遍历所有不在连通部分的点,找到离连通部分最近的点,将其加入连通部分
- 用该点到其他点的距离更新其他点到连通部分的距离
- 继续下一次迭代,直到所有点都加到最小生成树中(由于一次加一个点,所以n个点只需迭代n 次)
- 最后迭代n次后的连通部分就是该图的最小生成树。
图示
例题
Prim算法求最小生成树
#include <iostream>
#include <algorithm>
#include <cstring>
#define endl '\n'
using namespace std;
const int N = 505;
int n, m;
int g[N][N]; // 邻接矩阵存图
int dist[N]; // dist[i]表示当前i距离连通部分的距离
bool st[N]; // st标记当前点是否已经加入连通部分,st[i] = true说明已经加入了,st[i] = false说明还没加入int prim(){memset(dist, 0x3f, sizeof dist); // 一开始,连通部分没有点,所有点到连通部分的距离为正无穷int res = 0; // res记录当前加到最小生成树中的边的权值的总和for(int i = 0; i < n; i++){ // 迭代n次int t = -1; // t来记录未加入连通部分的点中距离连通部分最近的点for(int j = 1; j <= n; j++){ // 遍历所有不在连通部分的点, 找到离连通部分最近的点if(!st[j] && (t == -1 || dist[t] > dist[j])) // t == -1 : 防止越界; dist[t] > dist[j]:点j比点t距离连通部分近t = j; // 把t换成j}if(i && dist[t] == 0x3f3f3f3f) // 如果连通部分有点,离连通部分最近的点dist还是正无穷,说明图不连通return 0x3f3f3f3f;if(i)res += dist[t]; // 从第二个加入连通部分的点开始,把其距离连通部分的距离加到答案(也就是将其对应的边加入连通部分)st[t] = 1; // 标记一下这个点加进去了for(int j = 1; j <= n; j++)dist[j] = min(dist[j], g[t][j]); // 遍历所有点,用t到其他点的距离更新其他点到连通部分的距离}return res;
}int main(){ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);cin >> n >> m;memset(g, 0x3f, sizeof g); // 由于要取min,所以初始化成正无穷while(m--){int a, b, w;cin >> a >> b >> w;g[a][b] = g[b][a] = min(g[a][b], w); // 求最小生成树,如果有重边就只要最短边}int t = prim();if(t == 0x3f3f3f3f) cout << "impossible" << endl;else cout << t << endl;return 0;
}
最大生成树
在求最小生成树的基础上,Kruskal就是把正序排序换成逆序排序,Prim就是把大于小于号调换一下,灵活一点。
相关文章:
【算法笔记】图论基础(一):建图、存图、树和图的遍历、拓扑排序、最小生成树
目录 何为图论图的概念 图的一些基本概念有向图和无向图带权图连通图和非连通图对于无向图对于有向图 度对于无向图对于有向图一些结论 环自环、重边、简单图、完全图自环重边简单图 稀疏图和稠密图子图、生成子图同构 图的存储直接存边邻接矩阵存边邻接表存边链式前向星存边 图…...
Compose 原理解析
Compose 的组件都是放在 setContent() 之后才能显示的,那需要先看看这个函数的作用。 先看 ComponentActivity 的扩展函数 setContent(): /*** 将给定的可组合项合成到给定的 Activity 中。[content] 将成为给定 Activity 的根视图。* 这大致相当于使用…...
pyspark学习rdd处理数据方法——学习记录
python黑马程序员 """ 文件,按JSON字符串存储 1. 城市按销售额排名 2. 全部城市有哪些商品类别在售卖 3. 上海市有哪些商品类别在售卖 """ from pyspark import SparkConf, SparkContext import os import jsonos.environ[PYSPARK_P…...
个人学习编程(3-22) leetcode刷题
连续子数组:(难) 示例 1: 输入: nums [0,1] 输出: 2 说明: [0, 1] 是具有相同数量 0 和 1 的最长连续子数组。 示例 2: 输入: nums [0,1,0] 输出: 2 说明: [0, 1] (或 [1, 0]) 是具有相同数量0和1的最长连续子数组。 需要理解的知识&a…...
RabbitMQ八股文
RabbitMQ 核心概念与组件 1. RabbitMQ 核心组件及其作用 1.1 生产者(Producer) 作用:创建并发送消息到交换机。特点:不直接将消息发送到队列,而是通过交换机路由。 1.2 交换机(Exchange) 作…...
运维面试题(七)
1.statefulset用来管理有状态的应用程序,有状态是什么意思? 每一个pod都有一个固定的网络标识符,在整个生命周期中不会改变。每个实例都可以拥有自己的持久化存储卷,即使容器被删除并重新创建,存储卷仍然存在。Statef…...
【项目设计】网页版五子棋
文章目录 一、项目介绍1.项目简介2.开发环境3.核心技术4.开发阶段 二、Centos-7.6环境搭建1.安装wget工具2.更换软件源(yum源)3.安装scl工具4.安装epel软件源5.安装lrzsz传输工具6.安装高版本gcc/g编译器7.安装gdb调试器8.安装git9.安装cmake10.安装boost库11.安装Jsoncpp库12.…...
Netty——BIO、NIO 与 Netty
文章目录 1. 介绍1.1 BIO1.1.1 概念1.1.2 工作原理1.1.3 优缺点 1.2 NIO1.2.1 概念1.2.2 工作原理1.2.3 优缺点 1.3 Netty1.3.1 概念1.3.2 工作原理1.3.3 优点 2. Netty 与 Java NIO 的区别2.1 抽象层次2.2 API 易用性2.3 性能优化2.4 功能扩展性2.5 线程模型2.6 适用场景 3. 总…...
Docker 安装 Mysql
以下是安装Docker版MySQL 8.0.25并实现目录挂载的步骤: docker仓库:https://hub.docker.com/_/mysql 1. 拉取Mysql镜像文件 docker pull mysql:8.0.252. 创建mysql临时容器服务 docker run -d \--name mysql \-p 3306:3306 \-e MYSQL_ROOT_PASSWORD123…...
Electron打包文件生成.exe文件打开即可使用
1 、Electron 打包,包括需要下载的内容和环境配置步骤 注意:Electron 是一个使用 JavaScript、HTML 和 CSS 构建跨平台桌面应用程序的框架 首先需要电脑环境有Node.js 和 npm我之前的文章有关nvm下载node的说明也可以去官网下载 检查是否有node和npm环…...
线程和协程的区别了解
1.资源消耗 调度方式:线程由操作系统内核调度(抢占式),协程由程序自己控制调度(协作式)。切换开销:线程切换涉及内核态与用户态的转换,开销大;协程只在用户态切换上下文…...
楼宇自控系统的结构密码:总线与分布式结构方式的差异与应用
在现代建筑中,为了实现高效、智能的管理,楼宇自控系统变得越来越重要。它就像建筑的 智能管家,可自动控制照明、空调、通风等各种机电设备,让建筑运行更顺畅,还能节省能源成本。而在楼宇自控系统里,有两种关…...
算法及数据结构系列 - 滑动窗口
系列文章目录 算法及数据结构系列 - 二分查找 算法及数据结构系列 - BFS算法 算法及数据结构系列 - 动态规划 算法及数据结构系列 - 双指针 算法及数据结构系列 - 回溯算法 算法及数据结构系列 - 树 文章目录 滑动窗口框架思路经典题型76. 最小覆盖子串567. 字符串的排列438. …...
【江协科技STM32】软件SPI读写W25Q64芯片(学习笔记)
SPI通信协议及S为5Q64简介:【STM32】SPI通信协议&W25Q64Flash存储器芯片(学习笔记)-CSDN博客 STM32与W25Q64模块接线: SPI初始化: 片选SS、始终SCK、MOSI都是主机输出引脚,输出引脚配置为推挽输出&…...
2025.3.23机器学习笔记:文献阅读
2025.3.23周报 题目信息摘要Abstract创新点网络架构实验不足以及展望 题目信息 题目: Enhancement of Hydrological Time Series Prediction with Real-World Time Series Generative Adversarial Network-Based Synthetic Data and Deep Learning Models期刊&…...
Day20-前端Web案例——部门管理
目录 部门管理1. 前后端分离开发2. 准备工作2.1 创建Vue项目2.2 安装依赖2.3 精简项目 3. 页面布局3.1 介绍3.2 整体布局3.3 左侧菜单 4. Vue Router4.1 介绍4.2 入门4.3 案例4.4 首页制作 5. 部门管理5.1部门列表5.1.1. 基本布局5.1.2 加载数据5.1.3 程序优化 5.2 新增部门5.3…...
实验3 以太坊交易周期的需求分析
区块链技术 实验报告 实验名称 实验3 以太坊交易周期的需求分析 一、实验目的 1、学习并掌握以太坊交易的内容; 2、学习并掌握以太坊交易周期的四个阶段; 3、学习并掌握结构化需求分析方法; 4、学习并掌握面向对象的需求分析方法&…...
Linux 通过压缩包安装 MySQL 并设置远程连接教程
一、引言 在 Linux 系统中,有时候我们需要通过压缩包的方式手动安装 MySQL 数据库,并且为了方便在其他设备上对数据库进行管理和操作,还需要设置允许远程连接。本文将详细介绍在 Linux(以 CentOS 为例)系统中通过压缩包安装 MySQL 8 并设置远程连接的步骤。 二、安装前准…...
【商城实战(56)】商城数据生命线:恢复流程与演练全解析
【商城实战】专栏重磅来袭!这是一份专为开发者与电商从业者打造的超详细指南。从项目基础搭建,运用 uniapp、Element Plus、SpringBoot 搭建商城框架,到用户、商品、订单等核心模块开发,再到性能优化、安全加固、多端适配…...
Java学习笔记-XXH3哈希算法
XXH3是由Yann Collet设计的非加密哈希算法,属于XXHash系列的最新变种,专注于极速性能与低碰撞率,适用于对计算效率要求极高的场景。 极速性能 在RAM速度限制下运行,小数据(如 1-128 字节)处理可达纳秒级&…...
同旺科技USB to SPI 适配器 ---- 指令循环发送功能
所需设备: 内附链接 1、同旺科技USB to SPI 适配器 1、周期性的指令一次输入,即可以使用 “单次发送” 功能,也可以使用 “循环发送” 功能,大大减轻发送指令的编辑效率; 2、 “单次发送” 功能,“发送数据…...
在Mac M1/M2芯片上完美安装DeepCTR库:避坑指南与实战验证
让推荐算法在Apple Silicon上全速运行 概述 作为推荐系统领域的最经常用的明星库,DeepCTR集成了CTR预估、多任务学习等前沿模型实现。但在Apple Silicon架构的Mac设备上,安装过程常因ARM架构适配、依赖库版本冲突等问题受阻。本文通过20次环境搭建实测…...
【CXX-Qt】2.5 继承
某些 Qt API 要求你从抽象基类中重写某些方法,例如 QAbstractItemModel。 为了支持直接从 Rust 中创建这样的子类,CXX-Qt 提供了多种辅助工具。 某些基类可能需要特殊的构造参数。这可以通过使用自定义构造函数来实现。 访问基类方法 要在 Rust 中访…...
Linux系统之美:环境变量的概念以及基本操作
本节重点 理解环境变量的基本概念学会在指令和代码操作上查询更改环境变量环境变量表的基本概念父子进程间环境变量的继承与隔离 一、引入 1.1 自定义命令(我们的exe) 我们以往的Linux编程经验告诉我们,我们在对一段代码编译形成可执行文件后…...
【nnUnetv2】推理+评估+测试
在 Windows 系统下设置环境变量 之前训练和推理的时候开着AutoDL的服务器,是在 Linux 系统下设置的环境变量。 但是现在开始研究具体代码了,就在本地跑(一直开着服务器有点费钱),所以就在Windows 系统下设置环境变量。 ①右键点击 “此电脑”,选择 “属性”。 ②在左侧…...
损失函数理解(一)——极大似然估计
本博客内容来自B站up主【王木头学科学】的视频内容 习惯看视频的小伙伴可移至视频链接[待补充]:~~~ 首先通俗地解释一下极大似然估计(Maximum Likelihood Estimation,MLE)的思想:通过结果寻找使该结果发生的最可能的原…...
ios端使用TCplayer直播播放三秒直接卡顿bug
1. 查看配置项没问题 setTcPlayer() {let that this;player new TcPlayer("videoPlayer", {live: this.activatPlayType "livePlay" ? true : false,x5_type: "h5",x5_fullscreen: true,systemFullscreen: true,x5_orientation: 1,x5_player…...
大模型-提示词工程与架构
什么是提示工程 提示工程(Prompt Engineering)是一门新兴的技术领域,专注于研究如何设计、构建和优化提示词,以充分发挥大模型的潜力 。它涉及到对语言结构、任务需求、模型特性等多方面因素的综合考量。提示工程的目标是通过精心…...
高斯数据库-WDR Snapshot生成性能报告
docker 安装高斯数据库: docker pull opengauss/opengauss:latestdocker run --name opengauss --privilegedtrue -d -e GS_PASSWORDopenGauss123 -p 8090:5432 -v /opengauss:/var/lib/opengauss/data opengauss/opengauss:latest 进入容器设置用户权限ÿ…...
损失函数理解(二)——交叉熵损失
损失函数的目的是为了定量描述不同模型(例如神经网络模型和人脑模型)的差异。 交叉熵,顾名思义,与熵有关,先把模型换成熵这么一个数值,然后用这个数值比较不同模型之间的差异。 为什么要做这一步转换&…...
CSS学习笔记
【1】CSS样式规则 【2】CSS样式表引入方式 1、行内式 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"/><meta name"vi…...
AI比人脑更强,因为被植入思维模型【15】马斯洛需求层次理论
马斯洛需求层次模型思维模型 定义 马斯洛需求层次模型是由美国心理学家亚伯拉罕马斯洛(Abraham Maslow)于1943年提出的一种心理学理论,用于描述人类动机的层次结构。该模型将人类的需求从低到高分为五个层次,分别是生理需求、安…...
cartographer中地图转换
文章目录 地图种类栅格地图 坐标系种类ros坐标系像素坐标系物理坐标系(世界坐标系) 地图种类 栅格地图 地图的初始化 在Cartographer中,栅格地图通过概率值来表示每个栅格的状态。每个栅格的初始概率值通常设置为0.5,表示未知状态。这种初始化方式允许…...
关于MTU的使用(TCP/IP网络下载慢可能与此有关)
参考链接:告诉你mtu值怎么设置才能网速最好! -Win7系统之家 出现网络速度被限制,可能与MTU值相关,先查看下本机的MTU winR,然后输入:netsh interface ipv4 show subinterfaces ,查看自己网络中的MTU&…...
【AI解题】Cache直接映射地址划分解析
一、问题背景 某32位总线处理器的Cache采用直接映射方式,已知 Cache总容量为16KB,每个Cache块大小为16字节。需要确定内存地址中 Offset(块内偏移)、Index(块索引)、Tag(标签) 三部…...
android音频概念解析
音频硬件接口(我们可以理解为ASOC的声卡) 官方代码里叫audio hardware interface 也称为module,定义在services/audiopolicy/config/audio_policy_configuration.xml: 分别有primary,a2dp,usb࿰…...
项目生命周期 和 项目管理生命周期的差异
在项目管理中,明确区分 项目生命周期 和 项目管理生命周期 是理解项目运作的关键。以下从定义、阶段划分到实际应用进行系统性分析: 一、项目生命周期(Project Life Cycle) 定义 项目生命周期是项目从 启动到结束 的自然演进过程,描述项目交付成果的 技术性阶段,通常与…...
UDP 协议
文章目录 UDP 协议简介数据包格式UDP 通信流程抓包分析参考 本文为笔者学习以太网对网上资料归纳整理所做的笔记,文末均附有参考链接,如侵权,请联系删除。 UDP 协议 UDP 是一种面向无连接的传输层协议,属于 TCP/IP 协议簇的一种。…...
[已解决]jupyter notebook报错 500 : Internal Server Error及notebook闪退
jupyter notebook出现如上图的报错,可以在黑色窗口中检查是为什么报错。 我检查发现是nbconvert导致的问题,卸载重装nbconvert。 但是这时候出现,jupyter notebook闪退问题。jupyter的黑色窗口出现一秒钟就没了。 在Anaconda Prompt中检查ju…...
APM 仿真遥控指南
地面站开发了一段时间了,由于没有硬件,所以一直在 APM 模拟器中验证。我们已经实现了 MAVLink 消息接收和解析,显示无人机状态,给无人机发送消息,实现一键起飞,飞往指定地点,降落,返…...
使用 ncurses 库创建文本用户界面:基础函数详解
简介 ncurses 是一个功能强大的库,用于在 Unix-like 系统中创建文本用户界面。它提供了丰富的函数来控制屏幕上的文本显示、处理键盘输入、绘制图形元素等。本文将详细介绍 ncurses 库中的一些基础函数,包括 printw、wrefresh、获取用户信息、键盘输入、…...
dify创建第一个Agent
1、首先LLM模型必须支持 Function Calling 由于deepseek-R1本地化部署时还不支持,所以使用 qwq模型。 2、创建空白 Agent 3、为Agent添加工具 4、测试 当未添加时间工具时 询问 时间 如下 5、开启时间工具 询问如下...
nebula graph传统使用Docker进行项目发版
nebula graph传统使用Docker进行项目发版 1. nebula graph服务2. 搭建ES集群3. 注意事项3.1 图数据库的启动顺序3.2 模糊查询失效 1. nebula graph服务 1.在测试服务器中执行如下命令 docker commit 85b6e2b8xxx xxx_nebula_es:1.0.0.2执行docker images之后能看到新的镜像 x…...
OpenCV vs MediaPipe:哪种方案更适合实时手势识别?
引言 手势识别是计算机视觉的重要应用,在人机交互(HCI)、增强现实(AR)、虚拟现实(VR)、智能家居控制、游戏等领域有广泛的应用。实现实时手势识别的技术方案主要有基于传统计算机视觉的方法&am…...
PRODIGY: “不折腾人”的蛋白-蛋白/蛋白-小分子结合能计算工具
PRODIGY(全称为 PROtein binDIng enerGY prediction)是一种蛋白质结合能预测工具,可利用蛋白质-蛋白质复合物的三维结构来预测其结合亲和力。PRODIGY 利用一种高效的基于接触的方法,在估计结合自由能和解离常数的同时,…...
IDEA修改默认作者名称
User: IDEA提示注释缺少author信息,但自动设置后,名称不是我想要的默认名称,应该如何修改IDEA里默认的作者名称? Kimi: 以下是几种修改IntelliJ IDEA中默认作者名称的方法: ### 方法一:修改File and Code …...
【嵌入式学习2】C语言 - VScode环境搭建
目录 ## 语言分类 ## c语言编译器 ## VScode相关配置 ## 语言分类 编译型语言:C,C解释型语言:python,JS ## c语言编译器 分类GCC 系列MinGWCygwinMSVC系列一套编程语言编译器将GCC编译器和GNU Binutils移植到Win32平台下的产物…...
【TI MSPM0】Timer学习
一、计数器 加法计数器:每进入一个脉冲,就加一减法计算器:每进入一个脉冲,就减一 当计数器减到0,触发中断 1.最短计时时间 当时钟周期为1khz时,最短计时时间为1ms,最长计时时间为65535ms 当时…...
SQL Server数据库慢SQL调优
SQL Server中慢SQL会显著降低系统性能并引发级联效应。首先,用户直接体验响应时间延长,核心业务操作(如交易处理、报表生成)效率下降,导致客户满意度降低甚至业务中断。其次,资源利用率失衡,CPU…...
大数据平台上的数据建模与分析:从数据到决策的跃迁
大数据平台上的数据建模与分析:从数据到决策的跃迁 随着数字化转型的深入,大数据平台成为了企业实现智能决策和创新的核心技术基础。大量结构化、半结构化和非结构化数据的生成和存储,促使企业需要更高效的方式来管理、分析、以及从中提取有价值的信息。在这一过程中,数据…...