AK F.*ing leetcode 流浪计划之最近公共祖先(倍增算法)

欢迎关注更多精彩
关注我,学习常用算法与数据结构,一题多解,降维打击。

本期话题:在树上查找2个结点的最近公共祖先

问题提出

最近公共祖先定义

最近公共祖先简称 LCA(Lowest Common Ancestor)。两个节点的最近公共祖先,就是这两个点的公共祖先里面,离根最远(深度最深)的那个。

问题

参考地址:https://www.luogu.com.cn/problem/P3379
给定一棵树,询问每两个结点的最近公共祖先,一般会询问多次。

朴素做法

  1. 利用dfs求出所有结点的深度和父亲结点。
  2. 查询时把深度大的结点往上移,直到两个结点深度一样。然后两个结点同时往上移,直到两结点相遇。

复杂度分析

第1步求深度和父亲结点,需要遍历所有结点,复杂度是O(n)。
第2步在极端情况下是O(n) , 在多次查询的情况下,效率很低。

空间换时间

试想一下我们给每1个结点分配1个空间来存储往上移n个位置到达的祖先结点。
当我们要查询两个公共祖先时,就可以使用二分查找的方法来加速。


以A, B为例,可以看到后面黄色部分是公共祖先,我们要找的是最左边的10号祖先。只要利用二分查找即可找到。
该方法可以把查询复杂度降低到log(n). 但同时空间复杂度是O(n^2)。

优化空间(倍增算法)

参考资料:https://oi-wiki.org//graph/lca/#%E5%80%8D%E5%A2%9E%E7%AE%97%E6%B3%95
上面的方法的问题是空间分配的太多了,而且仔细观察,空间是冗余的。
比如A往上1个的祖先分配的数组和A的数组是高度重合的,可以看出是有递归或继承关系的。而且我们每次都是取的数组的一半。

那么我们可以存储往上数2^n个的祖先。
即存储往上1个,2个,4个。。。的祖先分别是谁。
查询的时候,由于任意数字都可以用2进制进行组合而成,可以遍历到所有祖先。
具体算法可以类比二分算法。

代码模板

题目链接:https://www.luogu.com.cn/problem/P3379

#include<stdio.h>
#include<malloc.h>
#include<string.h>
#include<cmath>
#include<algorithm>using namespace std;const int M = 500000 + 10;
const int N = 500000 + 10;
const int bitL = 22;
int head[N];
int to[M * 2], nextEdge[M * 2];
int len;
int h[N];
int father[bitL][N];void initPara(int n)
{len = 0;for (int i = 0; i < n; i++){head[i] = -1;}
}void add(int a, int b)
{to[len] = b;nextEdge[len] = head[a];head[a] = len++;
}void dfs(int x, int fa)
{if (fa == -1) h[x] = 0;else {h[x] = h[fa] + 1;father[0][x] = fa;// 利用倍增算法初始化fatherfor (int t = 1; t < bitL && (1<<t)<=h[x]; t++) {father[t][x] = father[t-1][father[t - 1][x]];}}int i;for (i = head[x]; i != -1; i = nextEdge[i]){int j = to[i];if (fa==j)continue;dfs(j, x);}
}int lca(int a, int b) {if (h[a] < h[b]) {return lca(b, a);}// 先将两个结点跳到一样高度int gap = h[a] - h[b];for (int t = bitL-1; t>=0; t--) {if (gap & (1 << t))a = father[t][a];}if (a == b)return a;gap = h[a];// 利用二分查找找到深度最低的且不一样的结点。for (int t = bitL-1; t >= 0; t--) {if (gap <=(1 << t))continue;if (father[t][a] == father[t][b])continue;a = father[t][a];b = father[t][b];gap -= 1 << t;}return father[0][a]; // 再往上1个既是公共祖先
}void solve()
{int t;int n, m, s;scanf("%d%d%d", &n, &m, &s);s--;initPara(n);int a, b;for (int i = 0; i < n - 1; ++i) {scanf("%d%d", &a, &b);a--, b--;add(a, b);add(b, a);}dfs(s, -1);/*for (int i = 0; i < n; ++i) {printf("%d: %d\n", i, h[i]);}*/while (m--) {scanf("%d%d", &a, &b);a--, b--;printf("%d\n", 1+lca(a, b));}
}void test() {int t;int n=5000, m=500000, s=1;//scanf("%d%d%d", &n, &m, &s);s--;initPara(n);int a, b;for (int i = 0; i < n - 1; ++i) {a = i, b = i + 1;add(a, b);add(b, a);}dfs(s, -1);//printf("%d\n", 1 + lca(10, 5000-1));while (m--) {a = (m+102)%n, b =( 3823+m*2)%n;//printf("%d\n", m);if(lca(a, b)!=min(a,b))printf("%d %d %d\n", 1 + lca(a, b), a+1, b+1);}
}int main()
{solve();//test();return 0;
}/*5 5 4
3 1
2 4
5 1
1 4
2 4
3 2
3 5
1 2
4 512 11 8
8 1
8 9
8 12
1 5
1 7
7 6
9 4
9 11
9 2
4 3
12 101 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10
10 11
11 12
*/

练习一

链接:https://loj.ac/p/10135
注意点:需要对结点进行编号,无公共祖先时返回-1


#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <cmath>
#include <algorithm>
#include <map>using namespace std;const int M = 500000 + 10;
const int N = 500000 + 10;map<int, int> num2Ind;
int indLen;void initIndex() {num2Ind.clear();indLen = 0;
}int getIndex(int n) {if (num2Ind.count(n) == 0)return -1;return num2Ind[n];
}int addIndex(int n) {if (num2Ind.count(n) == 0)num2Ind[n] = indLen++;return num2Ind[n];
}const int bitL = 22;
int head[N];
int to[M * 2], nextEdge[M * 2];
int len;
int h[N];
int father[bitL][N];void initPara(int n) {len = 0;for (int i = 0; i < n; i++) {head[i] = -1;}
}void add(int a, int b) {to[len] = b;nextEdge[len] = head[a];head[a] = len++;
}void dfs(int x, int fa) {if (fa == -1)h[x] = 0;else {h[x] = h[fa] + 1;father[0][x] = fa;for (int t = 1; t < bitL && (1 << t) <= h[x]; t++) {father[t][x] = father[t - 1][father[t - 1][x]];}}int i;for (i = head[x]; i != -1; i = nextEdge[i]) {int j = to[i];if (fa == j)continue;dfs(j, x);}
}int lca(int a, int b) {if (h[a] < h[b]) {return lca(b, a);}int gap = h[a] - h[b];for (int t = bitL - 1; t >= 0; t--) {if (gap & (1 << t))a = father[t][a];}if (a == b)return a;gap = h[a];for (int t = bitL - 1; t >= 0; t--) {if (gap <= (1 << t))continue;if (father[t][a] == father[t][b])continue;a = father[t][a];b = father[t][b];gap -= 1 << t;}return father[0][a];
}void solve() {int n, m;int a, b, s;scanf("%d", &n);initPara(n);for (int i = 0; i < n; ++i) {scanf("%d%d", &a, &b);if (b == -1) {s = addIndex(a);continue;}a = addIndex(a);b = addIndex(b);add(a, b);add(b, a);}dfs(s, -1);scanf("%d", &m);/*for (int i = 0; i < n; ++i) {printf("%d: %d\n", i, h[i]);}*/while (m--) {scanf("%d%d", &a, &b);a = getIndex(a);b = getIndex(b);if (a < 0 || b < 0 || a == b) {puts("0");continue;}int lcab = lca(a, b);if (lcab == a)puts("1");else if (lcab == b)puts("2");elseputs("0");}
}int main() {solve();return 0;
}/*
3
2 -1
1 2
3 1
2
1 2
2 32
1 -1
1 2
2
1 2
2 112
8 -1
8 1
8 9
8 12
1 5
1 7
7 6
9 4
9 11
9 2
4 3
12 10
11
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10
10 11
11 1210
234 -1
12 234
13 234
14 234
15 234
16 234
17 234
18 234
19 234
233 19
5
234 233
233 12
233 13
233 15
233 19
*/

练习二

链接:https://loj.ac/p/2610
算法思路:先用最小生成算法把所有大的边加入到树中。
利用倍增算法建立祖先关系,以及到祖先链路上的最小负载。
查询A,B最小负载为=min(A到公共祖先最小负载,B到公共祖先最小负载)。
具体实现分别从A,B查找最近公共祖先时记录链路上的最小值。
注意点:需要事先判断是否可达。题目中规定A!=B。
利用并查集点击前往判断是否在一棵树中。

#include<stdio.h>
#include<malloc.h>
#include<string.h>
#include<cmath>
#include<algorithm>
#include<vector>using namespace std;class UnionFindSet {
private:vector<int> father; // 父结点定义,father[i]=i时,i为本集合的代表vector<int> height; // 代表树高度,初始为1int nodeNum; // 集合中的点数public:UnionFindSet(int n); // 初始化bool Union(int x, int y); // 合并int Find(int x);bool UnionV2(int x, int y); // 合并int FindV2(int x);
};UnionFindSet::UnionFindSet(int n) : nodeNum(n + 1) {father = vector<int>(nodeNum);height = vector<int>(nodeNum);for (int i = 0; i < nodeNum; ++i) father[i] = i, height[i] = 1; // 初始为自己
}int UnionFindSet::Find(int x) {while (father[x] != x) x = father[x];return x;
}bool UnionFindSet::Union(int x, int y) {x = Find(x);y = Find(y);if (x == y)return false;father[x] = y;return true;
}int UnionFindSet::FindV2(int x) {int root = x; // 保存好路径上的头结点while (father[root] != root) {root = father[root];}/*从头结点开始一直往根上遍历把所有结点的father直接指向root。*/while (father[x] != x) {// 一定要先保存好下一个结点,下一步是要对father[x]进行赋值int temp = father[x];father[x] = root;x = temp;}return root;
}/*
需要加入height[]属性,初始化为1.
*/
//合并结点
bool UnionFindSet::UnionV2(int x, int y) {x = Find(x);y = Find(y);if (x == y) {return false;}if (height[x] < height[y]) {father[x] = y;}else if (height[x] > height[y]) {father[y] = x;}else {father[x] = y;height[y]++;}return true;
}const int M = 500000 + 10;
const int N = 500000 + 10;
const int bitL = 22;
int head[N];
int to[M * 2], nextEdge[M * 2], weight[M * 2];
int len;
int h[N];
int father[bitL][N];
int dis[bitL][N];void initPara(int n)
{len = 0;for (int i = 0; i < n; i++){head[i] = -1;h[i] = -1;}
}void add(int a, int b, int w)
{to[len] = b;weight[len] = w;nextEdge[len] = head[a];head[a] = len++;
}void dfs(int x, int fa, int w)
{if (fa == -1) h[x] = 0;else {h[x] = h[fa] + 1;father[0][x] = fa;dis[0][x] = w;for (int t = 1; t < bitL && (1 << t) <= h[x]; t++) {father[t][x] = father[t - 1][father[t - 1][x]];dis[t][x] = min(dis[t - 1][x], dis[t - 1][father[t - 1][x]]);}}int i;for (i = head[x]; i != -1; i = nextEdge[i]){int j = to[i];if (fa == j)continue;dfs(j, x, weight[i]);}
}int lca(int a, int b) {if (h[a] < h[b]) {return lca(b, a);}int gap = h[a] - h[b];for (int t = bitL - 1; t >= 0; t--) {if (gap & (1 << t))a = father[t][a];}if (a == b)return a;gap = h[a];for (int t = bitL - 1; t >= 0; t--) {if (gap <= (1 << t))continue;if (father[t][a] == father[t][b])continue;a = father[t][a];b = father[t][b];gap -= 1 << t;}return father[0][a];
}int optDis(int a, int b) {if (h[a] < h[b]) {return optDis(b, a);}int d = 1e6;int gap = h[a] - h[b];for (int t = bitL - 1; t >= 0; t--) {if (gap & (1 << t)) {d=min(d, dis[t][a]);a = father[t][a];}}if (a == b)return d;gap = h[a];for (int t = bitL - 1; t >= 0; t--) {if (gap <= (1 << t))continue;if (father[t][a] == father[t][b])continue;d = min(d,dis[t][a]);d = min(d,dis[t][b]);a = father[t][a];b = father[t][b];gap -= 1 << t;}d = min(d, min(dis[0][a], dis[0][b]));return d;
}bool cmp(vector<int> &a, vector<int> &b) {return a[2] > b[2];
}void solve()
{int n, m;int a, b, w;scanf("%d%d", &n, &m);initPara(n);auto us = UnionFindSet(n);vector<vector<int>> eds;for (int i = 0; i < m; ++i) {scanf("%d%d%d", &a, &b, &w);a--, b--;eds.push_back({a,b,w});}sort(eds.begin(), eds.end(), cmp);for (auto ed : eds) {if (us.UnionV2(ed[0], ed[1])) {add(ed[0], ed[1], ed[2]);add(ed[1], ed[0], ed[2]);}}for (int i = 0; i < n; ++i) {if(h[i]<0)dfs(i, -1, 0);}scanf("%d", &m);while (m--) {scanf("%d%d", &a, &b);a--, b--;if (us.FindV2(a) != us.FindV2(b))puts("-1");else printf("%d\n", optDis(a, b));}
}int main()
{solve();return 0;
}/*
12 11
8 1 4
8 9 3
8 12 6
1 5 5
1 7 1
7 6 2
9 4 2
9 11 10
9 2 9
4 3 2
12 10 711
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10
10 11
11 1212 11
8 1 1
8 9 1
8 12 1
1 5 1
1 7 1
7 6 1
9 4 1
9 11 1
9 2 1
4 3 1
12 10 111
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10
10 11
11 12*/

练习三

https://loj.ac/p/10130
算法思路:
利用倍增算法建立祖先关系,以及到祖先链路上的距离。
查询A,B距离=A到公共祖先距离+B到公共祖先距离)。
具体实现与上一题类似。

#include<stdio.h>
#include<malloc.h>
#include<string.h>
#include<cmath>
#include<algorithm>using namespace std;const int M = 500000 + 10;
const int N = 500000 + 10;
const int bitL = 22;
int head[N];
int to[M * 2], nextEdge[M * 2], weight[M * 2];
int len;
int h[N];
int father[bitL][N];
int dis[bitL][N];void initPara(int n)
{len = 0;for (int i = 0; i < n; i++){head[i] = -1;}
}void add(int a, int b, int w)
{to[len] = b;weight[len] = w;nextEdge[len] = head[a];head[a] = len++;
}void dfs(int x, int fa, int w)
{if (fa == -1) h[x] = 0;else {h[x] = h[fa] + 1;father[0][x] = fa;dis[0][x] = w;for (int t = 1; t < bitL && (1 << t) <= h[x]; t++) {father[t][x] = father[t - 1][father[t - 1][x]];dis[t][x] = dis[t - 1][x] + dis[t - 1][father[t - 1][x]];}}int i;for (i = head[x]; i != -1; i = nextEdge[i]){int j = to[i];if (fa == j)continue;dfs(j, x, weight[i]);}
}int lca(int a, int b) {if (h[a] < h[b]) {return lca(b, a);}int gap = h[a] - h[b];for (int t = bitL - 1; t >= 0; t--) {if (gap & (1 << t))a = father[t][a];}if (a == b)return a;gap = h[a];for (int t = bitL - 1; t >= 0; t--) {if (gap <= (1 << t))continue;if (father[t][a] == father[t][b])continue;a = father[t][a];b = father[t][b];gap -= 1 << t;}return father[0][a];
}int optDis(int a, int b) {if (h[a] < h[b]) {return optDis(b, a);}int d = 0;int gap = h[a] - h[b];for (int t = bitL - 1; t >= 0; t--) {if (gap & (1 << t)) {d += dis[t][a];a = father[t][a];}}if (a == b)return d;gap = h[a];for (int t = bitL - 1; t >= 0; t--) {if (gap <= (1 << t))continue;if (father[t][a] == father[t][b])continue;d += dis[t][a];d += dis[t][b];a = father[t][a];b = father[t][b];gap -= 1 << t;}d += dis[0][a] + dis[0][b];return d;
}void solve()
{int n, m;int a, b;scanf("%d", &n);initPara(n);for (int i = 0; i < n - 1; ++i) {scanf("%d%d", &a, &b);a--, b--;add(a, b, 1);add(b, a, 1);}dfs(0, -1, 0);scanf("%d", &m);while (m--) {scanf("%d%d", &a, &b);a--, b--;printf("%d\n", optDis(a, b));}
}int main()
{solve();return 0;
}/*
6
1 2
1 3
2 4
2 5
3 6
2
2 6
5 612
8 1
8 9
8 12
1 5
1 7
7 6
9 4
9 11
9 2
4 3
12 10
11
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10
10 11
11 12*/

练习四

https://acm.hdu.edu.cn/showproblem.php?pid=2586
与练习三类似

#include<stdio.h>
#include<malloc.h>
#include<string.h>
#include<cmath>
#include<algorithm>using namespace std;const int M = 500000 + 10;
const int N = 500000 + 10;
const int bitL = 22;
int head[N];
int to[M * 2], nextEdge[M * 2],weight[M*2];
int len;
int h[N];
int father[bitL][N];
int dis[bitL][N];void initPara(int n)
{len = 0;for (int i = 0; i < n; i++){head[i] = -1;}
}void add(int a, int b, int w)
{to[len] = b;weight[len] = w;nextEdge[len] = head[a];head[a] = len++;
}void dfs(int x, int fa, int w)
{if (fa == -1) h[x] = 0;else {h[x] = h[fa] + 1;father[0][x] = fa;dis[0][x] = w;for (int t = 1; t < bitL && (1<<t)<=h[x]; t++) {father[t][x] = father[t-1][father[t - 1][x]];dis[t][x] = dis[t-1][x]+ dis[t - 1][father[t - 1][x]];}}int i;for (i = head[x]; i != -1; i = nextEdge[i]){int j = to[i];if (fa==j)continue;dfs(j, x, weight[i]);}
}int lca(int a, int b) {if (h[a] < h[b]) {return lca(b, a);}int gap = h[a] - h[b];for (int t = bitL-1; t>=0; t--) {if (gap & (1 << t))a = father[t][a];}if (a == b)return a;gap = h[a];for (int t = bitL-1; t >= 0; t--) {if (gap <=(1 << t))continue;if (father[t][a] == father[t][b])continue;a = father[t][a];b = father[t][b];gap -= 1 << t;}return father[0][a];
}int optDis(int a, int b) {if (h[a] < h[b]) {return optDis(b, a);}int d = 0;int gap = h[a] - h[b];for (int t = bitL - 1; t >= 0; t--) {if (gap & (1 << t)) {d += dis[t][a];a = father[t][a];}}if (a == b)return d;gap = h[a];for (int t = bitL - 1; t >= 0; t--) {if (gap <= (1 << t))continue;if (father[t][a] == father[t][b])continue;d += dis[t][a];d += dis[t][b];a = father[t][a];b = father[t][b];gap -= 1 << t;}d += dis[0][a] + dis[0][b];return d;
}void solve()
{int t;int n, m;int a, b, w;scanf("%d", &t);while (t--) {scanf("%d%d", &n, &m);initPara(n);for (int i = 0; i < n - 1; ++i) {scanf("%d%d%d", &a, &b, &w);a--, b--;add(a, b,w);add(b, a,w);}dfs(0, -1, 0);/*for (int i = 0; i < n; ++i) {printf("%d: %d\n", i, h[i]);}*/while (m--) {scanf("%d%d", &a, &b);a--, b--;printf("%d\n", optDis(a,b));}}
}void test() {int t;int n = 5000, m = 500000;//scanf("%d%d%d", &n, &m, &s);initPara(n);int a, b;for (int i = 0; i < n - 1; ++i) {a = i, b = i + 1;add(a, b,1);add(b, a,1);}dfs(0, -1,0);//printf("%d\n", 1 + lca(10, 5000-1));while (m--) {a = (m+102)%n, b =( 3823+m*2)%n;//printf("%d\n", m);if(lca(a, b)!=min(a,b))printf("%d %d %d\n", 1 + lca(a, b), a+1, b+1);}
}int main()
{solve();//test();return 0;
}/*
2
3 2
1 2 10
3 1 15
1 2
2 32 2
1 2 100
1 2
2 11
12 11
8 1 4
8 9 3
8 12 6
1 5 5
1 7 1
7 6 2
9 4 2
9 11 10
9 2 9
4 3 2
12 10 71 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10
10 11
11 121
12 11
8 1 1
8 9 1
8 12 1
1 5 1
1 7 1
7 6 1
9 4 1
9 11 1
9 2 1
4 3 1
12 10 11 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10
10 11
11 12
*/

本人码农,希望通过自己的分享,让大家更容易学懂计算机知识。创作不易,帮忙点击公众号的链接。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/151586.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

机器学习算法分类

学习视频黑马程序员 监督学习 无监督学习 半监督学习 强化学习

Windows11 安全中心页面不可用问题(无法打开病毒和威胁防护)解决方案汇总(图文介绍版)

本文目录 Windows版本与报错信息问题详细图片&#xff1a; 解决方案:方案一、管理员权限&#xff08;若你确定你的电脑只有你一个账户&#xff0c;则此教程无效&#xff0c;若你也不清楚&#xff0c;请阅读后再做打算&#xff09;方案二、修改注册表(常用方案)方案三、进入开发…

【Python从入门到进阶】38、selenium关于Chrome handless的基本使用

接上篇《37、selenium关于phantomjs的基本使用》 上一篇我们介绍了有关phantomjs的相关知识&#xff0c;但由于selenium已经放弃PhantomJS&#xff0c;本篇我们来学习Chrome的无头版浏览器Chrome Handless的使用。 一、Chrome Headless简介 Chrome Headless是一个无界面的浏览…

mysql面试题22:SQL优化的一般步骤是什么,怎么看执行计划(explain),如何理解其中各个字段的含义

该文章专注于面试,面试只要回答关键点即可,不需要对框架有非常深入的回答,如果你想应付面试,是足够了,抓住关键点 面试官:SQL优化的一般步骤是什么,怎么看执行计划(explain),如何理解其中各个字段的含义 SQL优化的一般步骤如下: 分析和理解问题:首先,要确保对问…

CDN体系架构及部署方案探索

如今是科技技术飞速发展的时代&#xff0c;特别是互联网技术在各个方面都得到了质的提升。对于CDN技术来说&#xff0c;该项技术的基本功能、体系构架以及运营部署等方面都取得了长足的发展&#xff0c;不仅技术日新月异&#xff0c;而且整个体系日趋成熟&#xff0c;并且不断朝…

用全栈智能,联想如何“零故障”支持亚运会?

作者 | 曾响铃 文 | 响铃说 1912年&#xff0c;电子计时器首次应用&#xff0c;1936年&#xff0c;体育赛事首次在电视上播出&#xff0c;1972年计算机首次进入人类赛事&#xff0c;1996年互联网技术大范围应用&#xff0c;随后3G网络、3D技术、VR技术……以奥运会为代表&…

定时器+按键控制LED流水灯模式+定时器时钟——“51单片机”

各位CSDN的uu们好呀&#xff0c;今天&#xff0c;小雅兰的内容是51单片机中的定时器以及按键控制LED流水灯模式&定时器时钟&#xff0c;下面&#xff0c;让我们进入51单片机的世界吧&#xff01;&#xff01;&#xff01; 定时器 按键控制LED流水灯模式 定时器时钟 源代…

Legion Y9000X IRH8 2023款(82Y3)原装出厂OEM预装Windows11系统

lenovo联想电脑笔记本拯救者原厂win11系统镜像 下载链接&#xff1a;https://pan.baidu.com/s/15G01j7ROVqOFOETccQSKHg?pwdt1ju 系统自带所有驱动、出厂主题壁纸、Office办公软件、联想电脑管家等预装程序 所需要工具&#xff1a;32G或以上的U盘 文件格式&#xff1a;ISO…

Docker中将静态页面部署nginx

1.启动nginx docker start nginx 2.进入nginx cd /usr/share/nginx/html 3.vim index.html 说明&#xff1a;没有vim命令&#xff0c;docker镜像只保留了基本的功能&#xff08;文件&#xff09;。 4.解决方法 数据卷&#xff1a;是一个虚拟目录&#xff0c;是容器内目录与…

Python 无废话-办公自动化Excel修改数据

如何修改Excel 符合条件的数据&#xff1f;用Python 几行代码搞定。 需求&#xff1a;将销售明细表的产品名称为PG手机、HW手机、HW电脑的零售价格分别修改为4500、5500、7500&#xff0c;并保存Excel文件。如下图 Python 修改Excel 数据&#xff0c;常见步骤&#xff1a; 1&…

C++并发与多线程(4) | 传递临时对象作为线程参数的一些问题Ⅰ

一、陷阱1 写一个传递临时对象作为线程参数的示例: #include <iostream> #include <vector> #include <thread> using namespace std;void myprint(const int& i, char* pmybuf) {cout << i << endl;cout << pmybuf << endl;r…

git拉取代码过程

第一步&#xff1a;先在本地创建文件夹 &#xff0c;比如我这里的文件夹名称是 fengkgong_zntjfx 第二步&#xff1a;执行命令&#xff1a;git init 第三步&#xff1a;git clone 第四步&#xff1a;git fetch 第五步&#xff1a;git branch -a 第六步&#xff1a;cd 项目 【…

【大数据】Apache NiFi 助力数据处理及分发

Apache NiFi 助力数据处理及分发 1.什么是 NiFi &#xff1f;2.NiFi 的核心概念3.NiFi 的架构4.NiFi 的性能预期和特点5.NiFi 关键特性的高级概览 1.什么是 NiFi &#xff1f; 简单的说&#xff0c;NiFi 就是为了解决不同系统间数据自动流通问题而建立的。虽然 dataflow 这个术…

RabbitMQ-第四种交换机类型

接上文 RabbitMQ-主题模式 1 第四种交换机类型 header:它是根据头部信息来决定的&#xff0c;在我们发送的消息中是可以携带一些头部信息的&#xff0c;类似与HTTP&#xff0c;我们可以根据这些头部信息来决定路由到哪一个消息队列中。 修改配置类内容 Configuration public…

行车记录仪检测不到内存卡的原因

最近修了两个行车记录仪&#xff0c;相同的问题&#xff0c;都是提示插入内存卡&#xff08;TF卡&#xff09;。网上搜索资料&#xff0c;并没有明确的指出问题原因&#xff0c;有的是直接更换卡槽。 于是自己分析&#xff0c;首先内存卡电路属于小电流&#xff0c;而且电压并不…

2.1 关系数据结构及形式化定义

思维导图&#xff1a; 2.1.1 关系 笔记&#xff1a; 关系数据库模型是一个简单但强大的方式来表示数据及其之间的关系。下面是这节的关键内容&#xff1a; - **关系模型核心概念** * 关系数据模型的核心是“关系”&#xff0c;它在逻辑上表现为一个二维表。 * 此表中&a…

Scratch3.0下载

通俗易懂&#xff0c;直接上链接 链接&#xff1a;https://pan.baidu.com/s/1n-QFEQWT8im8BHQu1wIjtg?pwd1016 提取码&#xff1a;1016

2023学生近视了用什么台灯好呢?好用预防近视的护眼台灯推荐

自从护眼台灯能够帮助孩子在写作业时能够缓解视觉疲劳以来&#xff0c;许多家长已经给孩子安排上来护眼台灯&#xff0c;护眼台灯能够提供良好的照明环境&#xff0c;并且能够让我们专心学习提高工作效率。但由于护眼台灯含有独家的黑科技技术&#xff0c;价格始终居高不下&…

前端性能优化之防抖节流

前端性能优化之防抖&节流 1.什么是防抖和节流2.代码实现2.1 实现防抖2.2 实现节流 3.应用场景3.1 防抖的应用3.2 节流的应用 1.什么是防抖和节流 防抖和节流是前端开发中常用的两种性能优化技术。 为什么需要防抖和节流呢&#xff1f; 两者目的都是为了防止某个时间段内…

Linux登录自动执行脚本

一、所有用户每次登录时自动执行。 1、在/etc/profile文件末尾添加。 将启动命令添加到/etc/profile文件末尾。 2、在/etc/profile.d/目录下添加sh脚本。 在/etc/profile.d/目录下新建sh脚本&#xff0c;设置每次登录自动执行脚本。有用户登录时&#xff0c;/etc/profile会遍…