《数据结构》学习系列——图(中)
系列文章目录
目录
- 图的遍历
- 深度优先遍历
- 递归算法
- 堆栈算法
- 广度优先搜索
- 拓扑排序
- 定义定理
- 算法思想
- 伪代码
- 关键路径
- 基本概念
- 关键活动有关量
- 数学公式
- 伪代码
- 时间复杂性
图的遍历
- 从给定连通图的某一顶点出发,沿着一些边访问遍图中所有的顶点,且使每个顶点仅被访问一次,称为图的遍历(Graph Traversal)
- 存在的问题:图中可能存在回路,且图的任一顶点都可能与其它顶点相通,在访问完某个顶点之后可能会沿着某些边又回到曾经访问过的顶点。
- 避免重复访问:设置一个标志顶点是否被访问过的辅助数组 visited[],它的初始状态为 0。在图的遍历过程中,一旦某一个顶点 i i i 被访问,就立即让 visited[i] 置为 1,防止它被多次访问
深度优先遍历
- 深度优先遍历又被称为深度优先搜索 DFS (Depth First Search),其类似于树的先根遍历
- 基本思想:
- DFS在访问图中某一起始顶点 v v v 后,由 v v v 出发,访问它的任一邻接顶点 w 1 w_1 w1;再从 w 1 w_1 w1 出发,访问与 w 1 w_1 w1 邻接但还没有访问过的顶点 w 2 w_2 w2;然后再从 w 2 w_2 w2 出发,进行类似的访问。如此往下去,直至到达所有的邻接顶点都被访问过的顶点 u u u 为止。接着,退回一步,退到前一次访问过的顶点,看看还有其它没有被访问的邻接顶点。如果有,则访问此顶点,之后再从此顶点出发,进行与前述类似的访问;如果没有,就再退回一步进行搜索。重复上述过程,直到连通图中所有顶点都被访问过为止
- DFS在访问图中某一起始顶点 v v v 后,由 v v v 出发,访问它的任一邻接顶点 w 1 w_1 w1;再从 w 1 w_1 w1 出发,访问与 w 1 w_1 w1 邻接但还没有访问过的顶点 w 2 w_2 w2;然后再从 w 2 w_2 w2 出发,进行类似的访问。如此往下去,直至到达所有的邻接顶点都被访问过的顶点 u u u 为止。接着,退回一步,退到前一次访问过的顶点,看看还有其它没有被访问的邻接顶点。如果有,则访问此顶点,之后再从此顶点出发,进行与前述类似的访问;如果没有,就再退回一步进行搜索。重复上述过程,直到连通图中所有顶点都被访问过为止
递归算法
伪代码
// 图的深度优先遍历的递归算法
DepthFirstSearch(v, visited)
{visited[v] = 1;p = adjacent(Head[v]);while (p != NULL){if (visited[VerAdj(p) != 1]){DepthFirstSearch(VerAdj(p), visited)p = link(p); }}
}// 算法主体
DFS_Main()
{// 为辅助数组申请空间visited = new int[graphsize];// 数组初始化for (int k = 0; k < graphsize; k++){visited[k] = 0;// 从序号为0的顶点出发,深度优先遍历图DepthFirstSearch(0, visited)delete[] visited;}
}
非连通图需要多次调用深度优先遍历算法
for i = 0 to n-1
{for j = 0 to n-1{if visited[j] = 0{DepthFirstSearch(v[j], visited)}}
}
算法分析
- 图中有 n n n 个顶点, e e e 条边
- 如果用邻接表存储,沿顶点的adjacent可以找到某个顶点 v v v 的所有邻接顶点 w w w。由于总共有 2 e 2e 2e(无向图)或 e e e(有向图)个边结点,所以扫描边的时间为 O ( e ) O(e) O(e)。而且对所有顶点递归访问 1 次,所以遍历图的时间复杂性为 O ( n + e ) O(n + e) O(n+e)
- 如果用邻接矩阵存储,则查找每一个顶点的所有的边,所需时间为 O ( n ) O(n) O(n),则遍历图中所有的顶点所需的时间为 O ( n 2 ) O(n^2) O(n2)
堆栈算法
- 可以利用堆栈实现深度优先遍历的非递归算法
- 堆栈中存放已访问结点的还没有被访问的邻接顶点。每次弹出栈顶元素时,如其未被访问则访问该顶点,检查当前顶点的边链表,将还没有被访问的邻接顶点入栈,循环进行
基本思想
首先将所有顶点的visited[]值置为 0,初始顶点压入堆栈
- ① 检测堆栈是否为空。若堆栈为空,则迭代结束;否则,从栈顶弹出一个顶点 v v v
- ② 如果 v v v 未被访问过,则访问 v v v,将visited[v]值更新为 1,然后根据 v v v 的邻接顶点表,将 v v v 的未被访问的邻接顶点压入栈,执行步骤 ①
// 非递归实现深度优先遍历算法
void DFS(Graph &graph, int v) {stack<int> S; // 创建栈Svector<bool> visited(graph.size(), false); // 初始化访问标记数组S.push(v); // 将起始顶点压入栈while (!S.empty()) { // 当栈不为空时int v = S.top(); // 弹出栈顶元素S.pop();if (!visited[v]) {cout << v << " "; // 访问顶点visited[v] = true; // 标记为已访问// 获取顶点v的所有邻接顶点,并压入栈中for (auto p = graph.adjacent(v); p != nullptr; p = p->link) {if (!visited[p->VerAdj]) {S.push(p->VerAdj);}}}}
}
算法分析
- 如果使用邻接表表示图,则循环的总时间代价为 d 0 + d 1 + ⋯ + d n − 1 = O ( e ) d_0 + d_1 + \dots + d_{n-1} = O(e) d0+d1+⋯+dn−1=O(e),其中 d i d_i di 是顶点 i i i 的度(无向图)或出度(有向图)。总的时间复杂度为 O ( n + e ) O(n + e) O(n+e)
- 如果使用邻接矩阵,则对于每一个被访问的顶点,循环要检测矩阵中的 n n n 个元素,总的时间代价为 O ( n 2 ) O(n^2) O(n2)
广度优先搜索
- 为了实现逐层访问,算法中使用了一个队列,以记忆正在访问的这一层和上一层的顶点,以便于向下一层访问
- 与深度优先搜索过程一样,为避免重复访问,需要一个辅助数组visited[],为被访问过的顶点加标记
// BFS1 [初始化]
CREATEQ(Q); // 创建队列 Q
for (int i = 1; i <= n; i++) visited[i] = 0; // 初始化所有顶点为未访问
PRINT(v); // 打印起始顶点
visited[v] = 1; // 标记起始顶点为已访问
Q.enqueue(v); // 起始顶点入队列// BFS2 [广度优先遍历]
while (!Q.isEmpty()) { // 当队列不为空时v = Q.dequeue(); // 队头元素出队p = adjacent(Head[v]); // 获取当前顶点的邻接链表while (p != NULL) { // 遍历邻接链表if (visited[p->VerAdj] == 0) { // 如果邻接顶点未被访问Q.enqueue(p->VerAdj); // 将邻接顶点入队PRINT(p->VerAdj); // 打印邻接顶点visited[p->VerAdj] = 1; // 标记邻接顶点为已访问}p = p->link; // 继续访问下一个邻接顶点}
}
算法分析
- 如果使用邻接表表示图,则循环的总时间代价为 d 0 + d 1 + ⋯ + d n − 1 = O ( e ) d_0 + d_1 + \dots + d_{n-1} = O(e) d0+d1+⋯+dn−1=O(e),其中 d i d_i di 是顶点 i i i 的度。总的时间复杂度为 O ( n + e ) O(n + e) O(n+e)
- 如果使用邻接矩阵,则对于每一个被访问的顶点,循环要检测矩阵中的 n n n 个元素,总的时间代价为 O ( n 2 ) O(n^2) O(n2)
拓扑排序
- AOV 网:在有向图中,用顶点表示活动,用有向边表示活动之间的先后关系,称这样的有向图为AOV网 (Activity On Vertex Network)}
- 计划、施工过程、生产流程、程序流程等都是“工程”。除了很小的工程外,一般都把工程分为若干个叫做“活动”的子工程。完成了所有这些活动,这个工程就可以完成了
- 例如,计算机专业学生的学习就是一个工程,每一门课程的学习就是整个工程的一些活动。其中有些课程要求先修课程,有些则不要求。这样,在有些课程之间有先后关系,有些课程可以并行地学习
定义定理
- 在 AOV 网络中,如果活动 V i V_i Vi 必须在活动 V j V_j Vj 之前进行,则存在有向边 ⟨ V i , V j ⟩ \langle V_i, V_j \rangle ⟨Vi,Vj⟩
- AOV 网络中不能出现有向回路,即有向环。在 AOV 网络中如果出现了有向环,则意味着某项活动应以自己作为先决条件。因此,对给定的 AOV 网络,必须先判断它是否存在有向环
- 拓扑序列:AOV 网中所有顶点排成的线性序列,要求每个活动的所有前驱活动都排在该活动前面
- 拓扑排序:构造 AOV 网的拓扑序列的过程被称为拓扑排序
- 如果通过拓扑排序能将 AOV 网络的所有顶点都排入一个拓扑有序的序列中,则该 AOV 网络中必定不会出现有向环;相反,如果得不到满足要求的拓扑有序序列,则说明 AOV 网络中存在有向环,此 AOV 网络所代表的工程是不可行的
- 设图 G = ( V , E ) G = (V, E) G=(V,E) 是非循环图, V ( G ) ≠ ∅ V(G) \neq \emptyset V(G)=∅,则 G G G 中一定存在入度为零的顶点。
- 设 G = ( V , E ) G = (V, E) G=(V,E) 是非循环图, V ( G ) = { 1 , 2 , … , n } V(G) = \{1, 2, \dots, n\} V(G)={1,2,…,n}, e = ∣ E ( G ) ∣ e = |E(G)| e=∣E(G)∣。则算法是正确的,且算法的时间复杂性为 O ( n + e ) O(n + e) O(n+e)
算法思想
- 拓扑排序算法的基本步骤
- 从网中选择一个入度为 0 的顶点并将其输出
- 从网中删除该顶点及其所有出边
- 执行步骤 ① 和 ②,直至所有顶点都已输出,或网中剩余顶点入度均不为 0(说明网中存在回路,无法继续拓扑排序)
注意:对于任何无回路的 AOV 网,其顶点均可排成拓扑序列,但其拓扑序列未必唯一
伪代码
- 假定 AOV 网用邻接表的形式存储。为实现拓扑排序算法,事先需做好两项准备工作:
- 建立一个数组count[],count[i]的元素值为顶点 i i i 的入度;
- 建立一个堆栈,栈中存放入度为 0 的顶点,每当一个顶点的入度为 0,就将其压入栈
// TOrder1 [初始化]
// 计算 count 数组(每个顶点的入度)
for (int i = 1; i <= n; i++) count[i] = 0; // 初始化所有顶点的入度为 0// 遍历邻接表,计算每个顶点的入度
for (int i = 1; i <= n; i++) {p = adjacent(Head[i]); // 获取顶点 i 的邻接表头指针while (p != NULL) { // 遍历邻接表count[VerAdj(p)]++; // 更新邻接顶点的入度p = p->link; // 移动到下一个邻接点}
}// 拓扑排序
top = 0; // 栈顶指针初始化为 0// 将入度为 0 的顶点压入栈
for (int i = 1; i <= n; i++) {if (count[i] == 0) {stack[top] = i; // 顶点 i 入栈top++; // 栈顶指针加 1}
}for (int i = 1; i <= n; i++) {// 如果循环体执行了 n 次但栈为空,则说明图中存在回路if (top == 0) {PRINT("There is a cycle in the network!");RETURN;} else {// 栈顶元素出栈j = stack[top - 1];top--; // 栈顶指针减 1PRINT(j); // 输出顶点 j(拓扑序中的一个顶点)// 遍历顶点 j 的邻接表,更新邻接顶点的入度p = adjacent(Head[j]);while (p != NULL) {k = VerAdj(p); // 获取邻接顶点count[k]--; // 邻接顶点的入度减 1if (count[k] == 0) { // 如果邻接顶点入度变为 0,则压入栈stack[top] = k;top++;}p = p->link; // 继续遍历下一个邻接点}}
}
关键路径
基本概念
-
如果在有向无环的带权图中
- 用有向边表示一个工程中的各项活动 (Activity)
- 用边上的权值表示活动的持续时间 (Duration)
- 用顶点表示事件 (Event)
-
则这样的有向图叫做用边表示活动的网络,简称AOE (Activity On Edges) 网络
- 源点:表示整个工程的开始(入度为零)
- 汇点:表示整个工程的结束(出度为零)
-
在 AOE 网络中,有些活动必须顺序进行,有些活动可以并行进行
-
从源点到各个顶点,以至从源点到汇点的有向路径可能不止一条。这些路径的长度也可能不同。完成不同路径的活动所需的时间虽然不同,但只有各条路径上所有活动都完成了,整个工程才算完成
-
完成整个工程所需的时间取决于从源点到汇点的最长路径长度,即在这条路径上所有活动的持续时间之和。这条路径长度最长的路径被称为关键路径 (Critical Path)
-
关键路径:从源点到汇点具有最大长度的路径称为关键路径
-
路径长度:指路径上的各边权值之和
-
关键活动:关键路径上的活动
关键活动有关量
-
事件 v j v_j vj 的最早发生时间ve(j):
- 从源点 v 0 v_0 v0 到 v j v_j vj 的最长路径长度。
-
事件 v j v_j vj 的最迟发生时间vl(j):
- 保证汇点的最早发生时间不推迟(即不推迟整个工程完成时间)的前提下,事件 v j v_j vj 允许的最迟发生时间,等于ve(n-1)减去从 v j v_j vj 到 v n − 1 v_{n-1} vn−1 的最长路径长度
-
活动 a i a_i ai 的最早开始时间e(i):
- 设活动 a i a_i ai 在有向边 ⟨ v j , v k ⟩ \langle v_j, v_k \rangle ⟨vj,vk⟩ 上,e(i)是从源点 v 0 v_0 v0 到 v j v_j vj 的最长路径长度。因此e(i) = ve(j)
-
活动 a i a_i ai 的最迟开始时间l(i):
- l(i)是在不会引起时间延误的前提下,该活动允许的最迟开始时间。设活动 a i a_i ai 在有向边 ⟨ v j , v k ⟩ \langle v_j, v_k \rangle ⟨vj,vk⟩ 上,则 l ( i ) = vl(k) − weight ( ⟨ j , k ⟩ ) l(i) = \texttt{vl(k)} - \texttt{weight}(\langle j, k \rangle) l(i)=vl(k)−weight(⟨j,k⟩)
数学公式
-
求所有事件的最早发生时间}:
递推公式: // 拓扑排序正序
ve(k) = { 0 , k = 0 max { ve(j) + weight ( ⟨ j , k ⟩ ) } , ⟨ v j , v k ⟩ ∈ E ( G ) , k = 1 , 2 , … , n − 1 \texttt{ve(k)} = \begin{cases} 0, & k = 0 \\ \max\{\texttt{ve(j)} + \texttt{weight}(\langle j, k \rangle)\}, & \langle v_j, v_k \rangle \in E(G), \; k = 1, 2, \dots, n-1 \end{cases} ve(k)={0,max{ve(j)+weight(⟨j,k⟩)},k=0⟨vj,vk⟩∈E(G),k=1,2,…,n−1 -
求所有事件的最迟发生时间}:
递推公式:拓扑排序逆序
vl(j) = { ve(n-1) , j = n − 1 min { vl(k) − weight ( ⟨ j , k ⟩ ) } , ⟨ v j , v k ⟩ ∈ E ( G ) , j = n − 2 , n − 3 , … , 0 \texttt{vl(j)} = \begin{cases} \texttt{ve(n-1)}, & j = n-1 \\ \min\{\texttt{vl(k)} - \texttt{weight}(\langle j, k \rangle)\}, & \langle v_j, v_k \rangle \in E(G), \; j = n-2, n-3, \dots, 0 \end{cases} vl(j)={ve(n-1),min{vl(k)−weight(⟨j,k⟩)},j=n−1⟨vj,vk⟩∈E(G),j=n−2,n−3,…,0
伪代码
思路
求关键活动的基本步骤:
- 对 AOE 网进行拓扑排序,若网中有回路,则终止算法;按拓扑次序求出各顶点事件的最早发生时间 ve
- 按拓扑序列的逆序求出各顶点事件的最迟发生时间 vl
- 根据ve和vl的值,求出各活动的最早开始时间 e(i)与最迟开始时间l(i),若e(i) = l(i),则 i i i 是关键活动
// CPath1 - 计算事件的最早发生时间
// 初始化事件的最早发生时间
for (int i = 1; i <= n; i++) ve[i] = 0; // 最早发生时间初始化为 0// 按拓扑序计算事件的最早发生时间
for (int i = 1; i <= n; i++) {p = adjacent(Head[i]); // 获取顶点 i 的邻接表while (p != NULL) {k = VerAdj(p); // 获取邻接顶点if (ve[i] + cost(p) > ve[k]) // 更新最早发生时间ve[k] = ve[i] + cost(p);p = p->link; // 继续访问下一个邻接点}
}// CPath2 - 计算事件的最迟发生时间
// 初始化事件的最迟发生时间
for (int i = 1; i <= n; i++) vl[i] = ve[n]; // 最迟发生时间初始化为最后事件的最早时间// 按拓扑逆序计算事件的最迟发生时间
for (int i = n; i >= 1; i--) {p = adjacent(Head[i]); // 获取顶点 i 的邻接表while (p != NULL) {k = VerAdj(p); // 获取邻接顶点if (vl[k] - cost(p) < vl[i]) // 更新最迟发生时间vl[i] = vl[k] - cost(p);p = p->link; // 继续访问下一个邻接点}
}// CPath3 - 关键活动的最早开始时间和最迟开始时间
// 遍历所有活动,计算关键活动
for (int i = 1; i <= n; i++) {p = adjacent(Head[i]); // 获取顶点 i 的邻接表while (p != NULL) {k = VerAdj(p); // 获取邻接顶点e = ve[i]; // 最早开始时间l = vl[k] - cost(p); // 最迟开始时间if (e == l) // 如果最早时间等于最迟时间,则为关键活动PRINT("<", i, ",", k, "> is Critical Activity!");p = p->link; // 继续访问下一个邻接点}
}
时间复杂性
- 时间复杂性:对顶点进行拓扑排序的时间复杂性为 O ( n + e ) O(n + e) O(n+e),以拓扑次序求ve[i]和按拓扑逆序求vl[i]}时,所需时间均为 O ( e ) O(e) O(e)。求各个活动的e[k]和l[k]的时间复杂度为 O ( e ) O(e) O(e),整个算法的时间复杂性是 O ( n + e ) O(n + e) O(n+e)
- 定理 6.3:任意的非空 AOE 网至少存在一条关键路径
- 推论 6.1:假设边 ⟨ T i , T j ⟩ \langle T_i, T_j \rangle ⟨Ti,Tj⟩ 属于 AOE 网,则有
vl[j] − ve[i] ≥ Weight ( ⟨ T i , T j ⟩ ) \texttt{vl[j]} - \texttt{ve[i]} \geq \texttt{Weight}(\langle T_i, T_j \rangle) vl[j]−ve[i]≥Weight(⟨Ti,Tj⟩) - 且如果 ⟨ T i , T j ⟩ \langle T_i, T_j \rangle ⟨Ti,Tj⟩ 属于某一条关键路径,则有
vl[j] − ve[i] = Weight ( ⟨ T i , T j ⟩ ) . \texttt{vl[j]} - \texttt{ve[i]} = \texttt{Weight}(\langle T_i, T_j \rangle). vl[j]−ve[i]=Weight(⟨Ti,Tj⟩).
相关文章:
《数据结构》学习系列——图(中)
系列文章目录 目录 图的遍历深度优先遍历递归算法堆栈算法 广度优先搜索 拓扑排序定义定理算法思想伪代码 关键路径基本概念关键活动有关量数学公式伪代码时间复杂性 图的遍历 从给定连通图的某一顶点出发,沿着一些边访问遍图中所有的顶点,且使每个顶点…...
网络安全,文明上网(2)加强网络安全意识
前言 在当今这个数据驱动的时代,对网络安全保持高度警觉已经成为每个人的基本要求。 网络安全意识:信息时代的必备防御 网络已经成为我们生活中不可或缺的一部分,信息技术的快速进步使得我们对网络的依赖性日益增强。然而,网络安全…...
Laravel对接SLS日志服务
Laravel对接SLS日志服务(写入和读取) 1、下载阿里云的sdk #通过composer下载 composer require alibabacloud/aliyun-log-php-sdk#对应的git仓库 https://github.com/aliyun/aliyun-log-php-sdk2、创建sdk请求的service <?phpnamespace App\Ser…...
Kafka 工作流程解析:从 Broker 工作原理、节点的服役、退役、副本的生成到数据存储与读写优化
Kafka:分布式消息系统的核心原理与安装部署-CSDN博客 自定义 Kafka 脚本 kf-use.sh 的解析与功能与应用示例-CSDN博客 Kafka 生产者全面解析:从基础原理到高级实践-CSDN博客 Kafka 生产者优化与数据处理经验-CSDN博客 Kafka 工作流程解析:…...
基于 Flink 的车辆超速监测与数据存储的小实战
基于 Flink 的车辆超速监测与数据存储的小实战 一、实战背景与目标 在智能交通管理领域,实时监控车辆行驶速度并精准识别超速行为对于保障道路交通安全和维护交通秩序具有至关重要的意义。本项目旨在构建一个高效的数据处理系统,能够从 Kafka 的 topic…...
Shell 脚本基础(7):重定向详解
内容预览 ≧∀≦ゞ Shell 脚本基础(7):重定向详解声明1. 重定向基础概念1.1 输出重定向(> 和 >>)覆盖写入(>)追加写入(>>)输出到终端和文件࿰…...
04. 流程控制
一、流程控制 流程控制就是用来控制程序运行中各语句执行顺序的语句。基本的流程结构为:顺序结构,分支结构(或称选择结构),循环结构。 顺序结构:程序自上到下执行,中间没有任何判断和跳转&…...
基于卡尔曼滤波器的 PID 控制
基于卡尔曼滤波器的PID控制算法结合了经典控制理论和现代信号处理技术。卡尔曼滤波器(Kalman Filter, KF)可以对噪声数据进行平滑处理,从而改善PID控制器的性能,特别是在处理具有噪声和不确定性的系统时。以下是详细的设计过程&am…...
基于信创环境的信息化系统运行监控及运维需求及策略
随着信息技术的快速发展和国家对信息安全的日益重视,信创环境(信息技术应用创新环境)的建设已成为行业发展的重要趋势。本指南旨在为运维团队在基于信创环境的系统建设及运维过程中提供参考,确保项目顺利实施并满足各项技术指标和…...
leetCode 283.移动零
题目 给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。 请注意 ,必须在不复制数组的情况下原地对数组进行操作。示例 1: 输入: nums [0,1,0,3,12] 输出: [1,3,12,0,0]示例 2: 输入: nums [0] 输出:…...
Kali Linux语言设置成中文
要将Kali Linux设置成中国地区(简体中文),可以按照以下步骤进行操作: 一、更新软件包列表 打开Kali Linux的终端。 输入以下命令来更新软件包列表: sudo apt-get update 二、安装语言包(如果有就不用安装了…...
c#窗体列表框(combobox)应用——省市区列表选择实例
效果如下: designer.cs代码如下: using System.Collections.Generic;namespace 删除 {public partial class 省市区选择{private Dictionary<string, List<string>> provinceCityDictionary;private Dictionary<string,List<string&…...
kali中信息收集的一些常用工具
这里只是代表个人所见,所以肯定会有其他的没提到,希望大家体谅 前言 信息收集分为主动和被动的 主动就是通过自己的机器去和对方比如通信后获得的数据 被动是指不是在自己这里获取的,可以是第三方平台获取到的,与目标没有通信 …...
【CS61A 2024秋】Python入门课,全过程记录P2(Week3开始,更新中2024/11/24)
文章目录 关于基本介绍👋Week 3Mon Environments阅读材料Lab 02: Higher-Order Functions, Lambda ExpressionsQ1: WWPD: The Truth Will PrevailQ2: WWPD: Higher-Order FunctionsQ3: WWPD: Lambda 关于 个人博客,里面偶尔更新,最近比较忙。…...
python学习笔记(8)算法(1)数组
一、数组 数组是存储于一个连续空间且具有相同数据类型的元素集合。若将有限个类型相同的变量的集合命名,那么这个名称为数组名。组成数组的各个变量称为数组的分量,也称为数组的元素,有时也称为下标变量。用于区分数组的各个元素的数字编号…...
C++(进阶) 第1章 继承
C(进阶) 第1章 继承 文章目录 前言一、继承1.什么是继承2.继承的使用 二、继承方式1.private成员变量的(3种继承方式)继承2. private继承方式3.继承基类成员访问⽅式的变化 三、基类和派生类间的转换1.切片 四、 继承中的作⽤域1.隐藏规则&am…...
【Linux | 计网】TCP协议详解:从定义到连接管理机制
目录 1.TCP协议的定义: 2.TCP 协议段格式 3.TCP两种通信方式 4.确认应答(ACK)机制 解决“后发先至”问题 5.超时重传机制 那么, 超时的时间如何确定? 6.连接管理机制: 6.1.三次握手: 为什么需要3次握手,一次两次不行吗…...
SElinux学习
一、SElinux简介 SELinux是Security-Enhanced Linux的缩写,意思是安全强化的linux,传统的访问控制在我们开启权限后,系统进程可以直接访问.当我们对权限设置不严谨时,这种访问方式就是系统的安全漏洞。 所以在开启SElinux后 会…...
Spark核心组件解析:Executor、RDD与缓存优化
Spark核心组件解析:Executor、RDD与缓存优化 Spark Executor Executor 是 Spark 中用于执行任务(task)的执行单元,运行在 worker 上,但并不等同于 worker。实际上,Executor 是一组计算资源(如…...
阿里云cdn配置记录和nodejs手动安装
cdn 登录阿里云 域名解析权限 开启cdn,接引导流程, 源可以设置 域名或者ip等 配置好域名解析 上传https证书 图片不显示,后端开发需要配置 回源配置的回源协议 ,配置跟随客服端【如果浏览器多次重定向错误,客服或者改…...
【实战】基于urllib和BeautifulSoup爬取jsp网站的数据
文章目录 前言目标网站分析目标网页爬取数据解析导出数据其他问题处理分页检索及多关键字搜索去重cookie问题工具封装经验总结前言 网络数据爬取大致分为两类: 静态爬取:该种方式针对那种架构比较老的网站,使用模版方式,通过浏览器F12只能找到静态页面,找不到返回json数…...
cpp-httplib 框架
cpp-httplib 概述 主要特点 单文件库:cpp-httplib 是一个单文件头文件库,易于集成到现有项目中。你只需将 httplib.h 包含到项目中即可开始使用支持 HTTP 客户端和服务器:它不仅支持作为 HTTP 客户端发送请求,也支持构建 HTTP 服…...
GEE 案例——TVDI(Temperature Vegetation Dryness Index)指数
目录 简介 方法论 代码解释 函数 案例代码 单景影像的TVDI 影像集合批量计算TVDI 引用 结果 简介 本文中代码包含两个可用于计算 TVDI 的主要函数。其中一个函数用于仅根据一幅 NDVI 和一幅 LST 图像生成 TVDI(singleTVDI),另一个函数用于为多幅 NDVI 和多幅 LST …...
Java语言程序设计 选填题知识点总结
第一章 javac.exe是JDK提供的编译器public static void main (String args[])是Java应用程序主类中正确的main方法Java源文件是由若干个书写形式互相独立的类组成的Java语言的名字是印度尼西亚一个盛产咖啡的岛名Java源文件中可以有一个或多个类Java源文件的扩展名是.java如果…...
基于Springboot+Vue社区养老服务管理系统(源码+lw+讲解部署+PPT)
前言 详细视频演示 论文参考 系统介绍 系统概述 核心功能 用户角色与功能 具体实现截图 1. 服务信息查看功能 主要代码实现 截图: 2. 服务申请功能 主要代码实现 截图: 3. 公告信息查看功能 主要代码实现 截图: 4. 服务信息…...
Linux基本指令的使用
当然可以!以下是一些常用的Linux指令及其示例: 1. ls 列出目录内容。 ls 显示当前目录下的文件和文件夹。 ls -l 以详细格式列出文件和文件夹的信息(如权限、拥有者、大小等)。 2. cd 改变当前目录。 cd /path/to/dire…...
Momenta C++面试题及参考答案
vtable 的创建时机 在 C 中,vtable(虚函数表)是在编译阶段创建的。当一个类包含虚函数时,编译器会为这个类生成一个 vtable。vtable 本质上是一个函数指针数组,其中每个元素指向一个虚函数的实现。这个表的布局是由编译…...
AI 在软件开发流程中的优势、挑战及应对策略
AI 在软件开发流程中的优势、挑战及应对策略 随着人工智能技术的飞速发展,AI大模型正在逐步渗透到软件开发的各个环节,从代码自动生成到智能测试,AI的应用正在重塑传统的软件开发流程。本篇文章将分析AI在软件开发流程中带来的优势࿰…...
langchain runnable
LangChain 文档详细解析 LangChain 是一个用于构建与语言模型(如GPT-4)交互的框架。本文档介绍了LangChain v0.1版本中的Runnable接口及其相关功能。 目录 Runnable接口输入和输出模式使用示例异步方法事件流并行处理 1. Runnable接口 为了简化自定义…...
nginx配置不缓存资源
方法1 location / {index index.html index.htm;add_header Cache-Control no-cache,no-store;try_files $uri $uri/ /index.html;#include mime.types;if ($request_filename ~* .*\.(htm|html)$) {add_header Cache-Control "private, no-store, no-cache, must-revali…...
Linux系统程序设计--4.进程
程序与进程 内核中的进程结构 task_struct(进程表项和进程控制块) 位于/usr/src/linux-headers-4.15.0-213-generic/include/linux/sched.h C程序启动过程 进程终止方式 进程终止函数 atexit 小案例 #include<stdio.h> #include<string.h> #include<stdlib…...
springboot/ssm网购平台管理系统Java在线购物商城管理平台web电商源码
springboot/ssm网购平台管理系统Java在线购物商城管理平台web电商源码 基于springboot(可改ssm)vue项目 开发语言:Java 框架:springboot/可改ssm vue JDK版本:JDK1.8(或11) 服务器:tomcat 数据库&…...
2024年Android面试总结
2024年Android面试总结 1.动画类型有哪些?插值器原理? 2.StringBuffer和StringBuilder区别? 3.jvm内存模型? 4.线程池7大核心参数及原理? 5.Android多进程通信方式有哪些?各自的优缺点? 6…...
UE5 slate BlankProgram独立程序系列
源码版Engine\Source\Programs\中copy BlankProgram文件夹,重命名为ASlateLearning,修改所有文件命名及内部名称。 ASlateLearning.Target.cs // Copyright Epic Games, Inc. All Rights Reserved.using UnrealBuildTool; using System.Collections.Ge…...
小米PC电脑手机互联互通,小米妙享,小米电脑管家,老款小米笔记本怎么使用,其他品牌笔记本怎么使用,一分钟教会你
说在前面 之前我们体验过妙享中心,里面就有互联互通的全部能力,现在有了小米电脑管家,老款的笔记本竟然用不了,也可以理解,毕竟老款笔记本做系统研发的时候没有预留适配的文件补丁,至于其他品牌的winPC小米…...
家庭智慧工程师:如何通过科技提升家居生活质量
在今天的数字化时代,家居生活已经不再只是简单的“住”的地方。随着物联网(IoT)、人工智能(AI)以及自动化技术的快速发展,越来越多的家庭开始拥抱智慧家居技术,将他们的家变得更加智能化、便捷和…...
云计算-华为HCIA-学习笔记
笔者今年7月底考取了华为云计算方向的HCIE认证,回顾从IA到IE的学习和项目实战,想整合和分享自己的学习历程,欢迎志同道合的朋友们一起讨论! 第二章:服务器基础 服务器是什么? 服务器本质上就是个性能超强的…...
webgl threejs 云渲染(服务器渲染、后端渲染)解决方案
云渲染和流式传输共享三维模型场景 1、本地无需高端GPU设备即可提供三维项目渲染 云渲染和云流化媒体都可以让3D模型共享变得简单便捷。配备强大GPU的远程服务器早就可以处理密集的处理工作,而专有应用程序,用户也可以从任何个人设备查看全保真模型并与…...
【中间件】Redis
一、什么是Redis Redis是一个开源(BSD许可),内存存储的数据结构服务器,可用作数据库,高速缓存和消息队列代理。它支持字符串、哈希表、列表、集合、有序集合,位图,hyperloglogs等数据类型。内置…...
请结合给定资料中的具体事例,谈谈你对“海洋的污染将毁灭鱼儿的家园,但让人类不寒而栗的毁灭绝非仅此而已!”这句话的理解。(10分)
题目 【2010年国考省级以上(含副省级)申论真题】2.请结合给定资料中的具体事例,谈谈你对“海洋的污染将毁灭鱼儿的家园,但让人类不寒而栗的毁灭绝非仅此而已!”这句话的理解。(10分)…...
Java SE 与 Java EE:基础与进阶的探索之旅
在编程世界中,Java语言以其跨平台、面向对象、丰富的类库等特点,成为了众多开发者和企业的首选编程语言。而Java SE与Java EE,作为Java平台的两个重要组成部分,各自承载着不同的使命,同时又紧密相连,共同构…...
PH热榜 | 2024-11-24
DevNow 是一个精简的开源技术博客项目模版,支持 Vercel 一键部署,支持评论、搜索等功能,欢迎大家体验。 在线预览 1. AutoFlow Studio 标语:借助简化的AI质检,更快发布产品,更聪明地进行测试。 介绍&…...
LLM 系列学习教程
LLM101 检查 Tokenizer 词表大小与 LLM 的 Embedding 和 LM_head 输入大小是否匹配对 SBert 进行训练、预测、评估使其进行相似度计算对 BERT 进行训练、预测、评估使其进行文本分类使用 CLIP 模型进行文本图像匹配对 JoinBERT 进行训练、预测使其进行对话意图和槽位联合识别对…...
基于yolov8、yolov5的茶叶等级检测识别系统(含UI界面、训练好的模型、Python代码、数据集)
摘要:茶叶等级检测在茶叶生产、质量控制和市场销售中起着至关重要的作用,不仅能帮助相关部门实时监测茶叶质量,还为智能化检测系统提供了可靠的数据支撑。本文介绍了一款基于YOLOv8、YOLOv5等深度学习框架的茶叶等级检测模型,该模…...
Excel求和如何过滤错误值
一、问题的提出 平时,我们在使用Excel时,最常用的功能就是求和了,一说到求和你可能想到用sum函数,但是如果sum的求和区域有#value #Div等错误值怎么办?如下图,记算C列中工资的总和。 直接用肯定会报错&…...
头文件包含
大家好,今天我们来聊聊头文件包含这方面的知识,并且在这里提出几个问题,头文件多次包含有什么影响吗?“”和〈〉这两种方式都能包含标准头文件吗? 一.文件包含 #include指令可以使另外一个文件被编译。就像它实际出现…...
37_U-Net网络详解
1.U-Net 网络概述 U-Net 是一种深度学习模型,广泛用于图像的语义分割任务。U-Net 网络的结构特别适合医学影像分割,尤其在少量训练数据的情况下表现优异。该网络由一个编码器-解码器架构组成,具有对称的“U”形结构,因此得名为 U…...
fastapi入门
好的,我将为您生成一个更详细、易于理解的 FastAPI 入门学习文档,特别是对复杂概念(如依赖注入)进行深入解释,帮助您在没有太多基础的情况下也能顺利学习和掌握 FastAPI。 FastAPI 入门学习文档 目录 简介环境搭建 2…...
RabbitMQ 之 死信队列
一、死信的概念 先从概念解释上搞清楚这个定义,死信,顾名思义就是无法被消费的消息,字面意思可以这样理 解,一般来说,producer 将消息投递到 broker 或者直接到 queue 里了,consumer 从 queue 取出消息进行…...
Android-如何实现Apng动画播放
01 Apng是什么 Apng(Animated Portable Network Graphics)顾名思义是基于 PNG 格式扩展的一种动画格式,增加了对动画图像的支持,同时加入了 24 位图像和8位 Alpha 透明度的支持,并且向下兼容 PNG。 Google封面图 02 A…...