【数据结构1-2】二叉树

树形结构不仅能表示数据间的指向关系,还能表示出数据的层次关系,而有很明显的递归性质。因此,我们可以利用树的性质解决更多种类的问题。

但是在平常的使用中,我们并不需要使用这么复杂的结构,只需要建立一个包含int right和int left的结构体即可,left和right用于指示该节点的左儿子和右儿子。


一、【P4913】二叉树深度(递归/层次遍历)

本题的重点在于二叉树的存储和二叉树的层次遍历。

1. 二叉树存储:考虑一个二叉树的每个节点都有两个子节点,所以我们可以考虑用一个结构体来存储。其中,leftright分别代表节点的左节点编号和右节点编号。

struct node {int left, right;
};
node tree[MAXN];

2. 二叉树层次遍历:我们可以从根节点出发,先递归遍历该节点的左节点,再递归遍历该节点的右节点。对于每个父亲节点,先比较左右子树的高度,然后选取较高的子树,将其深度加1,每次遍历更新子树的高度。当遍历到叶子节点后返回0(叶子节点的左右子树高度均为0)。

int maxDepth(int id)
{if (id == 0) return 0;return 1 + max(maxDepth(Tree[id].left), maxDepth(Tree[id].right));
}

AC代码:

#include <iostream>
#include <string>
#include <algorithm>
#include <cmath>using namespace std;struct node
{int left;int right;
}Tree[1000005];int maxDepth(int id)
{if (id == 0) return 0;return 1 + max(maxDepth(Tree[id].left), maxDepth(Tree[id].right));
}int main()
{int n;	cin >> n;for (int i = 1; i <= n; i++){int a, b;	cin >> a >> b;Tree[i].left = a;Tree[i].right = b;}cout << maxDepth(1);}

二、【P1827】美国血统(前中后序遍历)

前序遍历、中序遍历和后序遍历是三种利用深度优先搜索遍历二叉树的方式。它们是在对节点访问的顺序有一点不同,其它完全相同。

需要注意的是下图中伪代码并未给出base case,即递归返回的条件。

AC代码:

先序遍历的特点是优先遍历根节点,所以整棵树的根应该会在inorder字符串的最开始出现;中序遍历的特点是优先遍历左子树,然后遍历根节点,所以我们可以根据中序遍历序列判断左右子树中包含哪些点。

以本题为例:

中序(inorder)遍历:ABEDFCHG;先序(preorder)遍历:CBADEFGH。

  1. 首先可以根据preorder判断C为根节点,然后依据inorder判断ABEDF为左子树中的节点,HG为右子树中的节点。
  2. 回到preorder序列,第二个节点是B,所以左子树的根节点为B,依据inorder序列可知A构成次级左子树,DEF构成次级右子树。
  3. 回到preorder序列,第三个节点是A,刚好是以B为根的子树的左子树的根;第四个节点是D,所以以B为根的子树的右子树的根为D。
  4. 以此类推,可以还原整棵树的情况。
#include <iostream>
#include <string>
#include <algorithm>
#include <cmath>
#include <vector>
#include <map>
#include <stack>
#include <set>using namespace std;struct TreeNode //建树
{char val;TreeNode* left;TreeNode* right;TreeNode() :val(0), left(nullptr), right(nullptr) {}TreeNode(char x) : val(x), left(nullptr), right(nullptr) {}TreeNode(char x, TreeNode* left, TreeNode* right) : val(x), left(left), right(right) {}
};//对preorder中的[s0,e0]部分操作,s1用于跟踪preorder序列中某个父亲节点
TreeNode* buildTree(string& preorder, map<char, int>& mp, int s0, int e0, int s1)
{if (s0 > e0) return nullptr;char mid = preorder[s1];int index = mp[mid]; //找到当前父亲节点在中序遍历inorder中的位置int left_length = index - s0; //左子树大小TreeNode* node = new TreeNode(mid);node->left = buildTree(preorder, mp, s0, index - 1, s1 + 1);node->right = buildTree(preorder, mp, index + 1, e0, s1 + 1 + left_length);return node;
}void PostOrder(TreeNode* tree)
{if (!tree) return;PostOrder(tree->left);PostOrder(tree->right);cout << tree->val;
}int main()
{string preorder, inorder;cin >> inorder >> preorder;map<char, int> mp;//使用map存储,便于搜索for (int i = 0; i < inorder.length(); i++)mp[inorder[i]] = i;TreeNode* res = buildTree(preorder, mp, 0, inorder.length() - 1, 0);PostOrder(res);
}

 由于需要通过preorder序列的节点,查询该点在inorder序列的位置,所以将inorder序列用map存储,实现O(1)量级的查询。

使用buildTree函数递归还原整棵树,然后使用postorder函数对树进行后序遍历,得到答案。


三、【P1229】遍历问题(前中后序遍历)

思路:给定inorder能确定树的具体结构,是因为可以确定子树是左子树还是右子树;而只给定preorder和postorder,则不能确定,这就是会出现不同树结构的原因。

只有前和后,那么主要问题就是没有办法处理只有一个子树的情况,因为这种情况下不知道子树究竟是这个节点的左子树还是右子树,也就是说其实这道题要判断遍历中存在着多少个只有一棵子树的情况。对于前,如果一个结点的下个结点等于后中对应结点的前一个结点的话,那么这个结点就是根节点且其只有一个子树。sum初始化为1,出现一个只有一棵子树的情况,就把sum*2(每次会出现两种不同的情况,分别是出现左子树和出现右子树)。

AC代码:

#include <iostream>
#include <string>
#include <algorithm>
#include <cmath>
#include <vector>
#include <map>
#include <cstring>
#include <queue>using namespace std;
const int INF = 0x7fffffff;int main()
{string preorder, postorder;cin >> preorder >> postorder;int sum = 1;for (int i = 0; i <= preorder.length() - 2; i++){for (int j = 0; j <= postorder.length() - 1; j++){if (preorder[i] == postorder[j] && preorder[i + 1] == postorder[j - 1]){sum *= 2;}}}cout << sum << endl;
}

四、【P1030】求先序序列(前中后序遍历)

首先,一点基本常识,给你一个后序遍历,那么最后一个就是根(如ABCD,则根为D),因为题目求先序,意味着要不断找根。

那么我们来看这道题方法:(示例)

中序ACGDBHZKX,后序CDGAHXKZB,首先可找到主根B;

那么我们找到中序遍历中的B,由这种遍历的性质,可将中序遍历分为ACGD和HZKX两棵子树,那么对应可找到后序遍历CDGA和HXKZ(从头找即可);从而问题就变成求:

  1. 中序遍历ACGD,后序遍历CDGA的树;
  2. 中序遍历HZKX,后序遍历HXKZ的树;

接着递归,按照原先方法,找到

1.子根A,再分为两棵子树;

2.子根Z,再分为两棵子树。

就按这样一直做下去(先输出根,再递归)。

模板概括为:

  • step1:找到根并输出
  • step2:将中序,后序各分为左右两棵子树;
  • step3:递归,重复step1,2;

AC代码:

#include <iostream>
#include <string>
#include <algorithm>
#include <cmath>
#include <vector>
#include <map>
#include <cstring>
#include <queue>using namespace std;
const int INF = 0x7fffffff;string inorder, postorder;void preorder(string in,string after)
{if (in.size() > 0){char ch = after[after.size() - 1];cout << ch;int k = in.find(ch);preorder(in.substr(0, k), after.substr(0, k)); //左子树preorder(in.substr(k + 1), after.substr(k, in.size() - k - 1));//从k开始,截取这么多个数}
}int main()
{cin >> inorder >> postorder;preorder(inorder, postorder);
}

将2,3,4三题进行比较,2的解题思路具有普适性,但是建树的过程相对复杂;4的解题思路较为清晰,但是缺点在于只能输出序列,并不能得到完整的树。


五、【P5076】简化二叉树(二叉搜索树)

参考:https://www.cnblogs.com/do-while-true/p/13566274.html 

但值得强调的是,二叉搜索树是一种低级的平衡二叉树,因为在最差情况下,可以会呈现链状结构,导致时间复杂度为O(n),而不是所需的O(logN)。因此,只需要了解即可,重点需要掌握的是平衡二叉树。

splay搜索树的几种操作:

(1)插入:x 是当前节点的下标,v 是要插入的值。要在树上插入一个 v 的值,就要找到一个合适 v 的位置,如果本身树的节点内有代表 v 的值的节点,就把该节点的计数器加 11 ,否则一直向下寻找,直到找到叶子节点,这个时候就可以从这个叶子节点连出一个儿子,代表 v 的节点。具体向下寻找该走左儿子还是右儿子是根据二叉搜索树的性质来的。

void add(int x,int v)
{tree[x].siz++;//如果查到这个节点,说明这个节点的子树里面肯定是有v的,所以siz++if(tree[x].val==v){//如果恰好有重复的数,就把cnt++,退出即可,因为我们要满足第四条性质tree[x].cnt++;return ;}if(tree[x].val>v){//如果v<tree[x].val,说明v实在x的左子树里if(tree[x].ls!=0)add(tree[x].ls,v);//如果x有左子树,就去x的左子树else{//如果不是,v就是x的左子树的权值cont++;//cont是目前BST一共有几个节点tree[cont].val=v;tree[cont].siz=tree[cont].cnt=1;tree[x].ls=cont;}}else{//右子树同理if(tree[x].rs!=0)add(tree[x].rs,v);else{cont++;tree[cont].val=v;tree[cont].siz=tree[cont].cnt=1;tree[x].rs=cont;}}
}

 (2)找前驱:x 是当前的节点的下标,val 是要找前驱的值,ans 是目前找到的比 val 小的数的最大值。找前驱的方法也是不断的在树上向下爬找具体节点,具体爬的方法可以参考代码注释部分。

int queryfr(int x, int val, int ans) {if (tree[x].val>=val){//如果当前值大于val,就说明查的数大了,所以要往左子树找if (tree[x].ls==0)//如果没有左子树就直接返回找到的ansreturn ans;else//如果不是的话,去查左子树return queryfr(tree[x].ls,val,ans);}else{//如果当前值小于val,就说明我们找比val小的了if (tree[x].rs==0)//如果没有右孩子,就返回tree[x].val,因为走到这一步时,我们后找到的一定比先找到的大(参考第二条性质)return (tree[x].val<val) ? tree[x].val : ans//如果有右孩子,,我们还要找这个节点的右子树,因为万一右子树有比当前节点还大并且小于要找的val的话,ans需要更新if (tree[x].cnt!=0)//如果当前节数的个数不为0,ans就可以更新为tree[x].valreturn queryfr(tree[x].rs,val,tree[x].val);else//反之ans不需要更新return queryfr(tree[x].rs,val,ans);}
}

(3)找后继:与找前驱同理,只不过需要反过来。

int queryne(int x, int val, int ans) {if (tree[x].val<=val){if (tree[x].rs==0)return ans;elsereturn queryne(tree[x].rs,val,ans);}else{if (tree[x].ls==0)return (tree[x].val>val)? tree[x].val : ans;if (tree[x].cnt!=0)return queryne(tree[x].ls,val,tree[x].val);elsereturn queryne(tree[x].ls,val,ans);}
}

(4)按值找排名:这里我们就要用到 siz 了,排名就是比这个值要小的数的个数再 +1,所以我们按值找排名,就可以看做找比这个值小的数的个数,最后加上 1 即可。

int queryval(int x,int val)
{if(x==0) return 0;//没有排名 if(val==tree[x].val) return tree[tree[x].ls].siz;//如果当前节点值=val,则我们加上现在比val小的数的个数,也就是它左子树的大小 if(val<tree[x].val) return queryval(tree[x].ls,val);//如果当前节点值比val大了,我们就去它的左子树找val,因为左子树的节点值一定是小的 return queryval(tree[x].rs,val)+tree[tree[x].ls].siz+tree[x].cnt;//如果当前节点值比val小了,我们就去它的右子树找val,同时加上左子树的大小和这个节点的值出现次数 //因为这个节点的值小于val,这个节点的左子树的各个节点的值一定也小于val 
}
//注:这里最终返回的是排名-1,也就是比val小的数的个数,在输出的时候记得+1

(5)按排名找值:排名为 n 的数在BST上是第 n 靠左的数。或者说排名为 n 的数的节点在BST中,它的左子树的 siz 与它的各个祖先的左子树的 siz 相加恰好 =n (这里相加是要减去重复部分)。

int queryrk(int x,int rk)
{if(x==0) return INF; if(tree[tree[x].ls].siz>=rk)//如果左子树大小>=rk了,就说明答案在左子树里 return queryrk(tree[x].ls,rk);//查左子树 if(tree[tree[x].ls].siz+tree[x].cnt>=rk)//如果左子树大小加上当前的数的多少恰好>=k,说明我们找到答案了 return tree[x].val;//直接返回权值 return queryrk(tree[x].rs,rk-tree[tree[x].ls].siz-tree[x].cnt);//否则就查右子树,同时减去当前节点的次数与左子树的大小 
}

AC代码:

#include <iostream>
#include <string>
#include <algorithm>
#include <cmath>
#include <vector>
#include <map>
#include <stack>
#include <set>using namespace std;
const int INF = 0x7fffffff;struct node
{int val; //节点值int left, right; //左右子树int cnt; //计数器int siz; //子树大小
}tree[100005];
int cont = 0;//记录节点数量//初始化
void init()
{for (int i = 0; i < 100005; i++){tree[i].val = 0;tree[i].left = 0;tree[i].right = 0;tree[i].cnt = 0;tree[i].siz = 0;}
}//添加新点
void add(int x, int value) //当前节点为x,需要插入value
{tree[x].siz++; //肯定在x子树上,规模加一if (tree[x].val == value) //如果value刚好等于节点值,计数器加一即可{tree[x].cnt++;return;}if (tree[x].val > value) //如果x的值大于value,value只能放在x的左子树上{if (tree[x].left != 0)//如果左子树上有节点,递归查找add(tree[x].left, value);else//如果左子树上没有点,直接添加{cont++;tree[cont].val = value;tree[cont].siz = tree[cont].cnt = 1;tree[x].left = cont;}}else if (tree[x].val < value)//如果x的值小于value,value要放到x的右子树上{if (tree[x].right != 0)//如果右子树上有节点,递归查找add(tree[x].right, value);else//如果右子树上没有点,直接添加{cont++;tree[cont].val = value;tree[cont].siz = tree[cont].cnt = 1;tree[x].right = cont;}}
}//查找前驱
int query_front(int x, int value, int ans) //x 是当前的节点的下标,val 是要找前驱的值,ans 是目前找到的比val小的数的最大值。
{if (cont == 0) return -INF;if (tree[x].val >= value)//当前节点val大于所查value,到左子树查找{if (tree[x].left == 0) //左子树不存在,那么前驱为ansreturn ans;elsereturn query_front(tree[x].left, value, ans); //否则遍历左子树}else{if (tree[x].right == 0)//若无右孩子,说明当前点满足条件return (tree[x].val < value) ? tree[x].val : ans;else{if (tree[x].cnt != 0) //如果当前节点的个数不为0,ans就可以更新为tree[x].valreturn query_front(tree[x].right, value, tree[x].val);elsereturn query_front(tree[x].right, value, ans);}}
}//查找后继
int query_next(int x, int value, int ans)
{if (cont == 0) return INF;if (tree[x].val <= value){if (tree[x].right == 0)return ans;elsereturn query_next(tree[x].right, value, ans);}else{if (tree[x].left == 0)return (tree[x].val > value) ? tree[x].val : ans;else{if (tree[x].cnt != 0)return query_next(tree[x].left, value, tree[x].val);elsereturn query_next(tree[x].left, value, ans);}}
}//按值找排名
int val_to_rank(int x, int value)
{if (x == 0) return 0;if (value == tree[x].val)return tree[tree[x].left].siz;//比它小的数if (value < tree[x].val)return val_to_rank(tree[x].left, value);if (value > tree[x].val)return val_to_rank(tree[x].right, value) + tree[tree[x].left].siz + tree[x].cnt;//左子树上的所有点加上根上的点都小于value
}//按排名找值
int rank_to_val(int x, int rank)
{if (x == 0)return INF;if (tree[tree[x].left].siz >= rank) //如果小于x.val的数多于rank,那么该值一定在左子树上,递归查找return rank_to_val(tree[x].left, rank);if (tree[tree[x].left].siz + tree[x].cnt >= rank) //如果左子树上的点数+根上的节点数大于rank,且左子树上的点数小于rank,那么点x的值为所需值return tree[x].val;return rank_to_val(tree[x].right, rank - tree[tree[x].left].siz - tree[x].cnt); //否则在右子树上,要先将左子树+根上的点数减去
}int main()
{int q;	cin >> q;init();for (int i = 1; i <= q; i++){int op, v;cin >> op >> v;if (op == 1)cout << val_to_rank(1, v) + 1 << endl;else if (op == 2)cout << rank_to_val(1, v) << endl;else if (op == 3)cout << query_front(1, v, -INF) << endl;else if (op == 4)cout << query_next(1, v, INF) << endl;else{if (cont == 0){cont++;tree[cont].cnt = tree[cont].siz = 1;tree[cont].val = v;}elseadd(1, v);}}
}

六、【P1364】医院设置(BFS广搜)

广度优先搜索(breadth-first search, BFS)不同与深度优先搜索,它是一层层进行遍历的,因此需要用先入先出的队列而非先入后出的栈进行遍历。由于是按层次进行遍历,广度优先搜索时按照“广”的方向进行遍历的,也常常用来处理最短路径等问题。

在本题中,由于每个点都可以是原点(树根),因此采用树结构存储是行不通的,因为指针只能单方向指向。这里采用邻接矩阵的方式来存储树。

AC代码:

本题中只考虑每个点到根节点的距离,因此采用DFS和BFS均可。

由于BFS操作起来更直观,因此本题用普通图的形式存储树,枚举每个节点为根节点的情况,进行n遍BFS,然后每遍都进行答案的比较更新。

#include <iostream>
#include <string>
#include <algorithm>
#include <cmath>
#include <vector>
#include <map>
#include <cstring>
#include <queue>using namespace std;
const int INF = 0x7fffffff;bool graph[105][105] = { 0 };
bool visit[105] = { 0 };
int value[105] = { 0 };struct node
{int num;int step; //用于存储某点到根节点的距离
};
int n;int BFS(int x) //以x为根对树进行BFS遍历
{memset(visit, 0, sizeof(visit)); queue<node> q;visit[x] = 1;node gen; gen.num = x, gen.step = 0;q.push(gen); //将树根节点入队int sum = 0;while (!q.empty()){node now = q.front();q.pop();for (int i = 1; i <= n; i++) //依次取出队列中的点,并找到与该点距离为1且未被访问过的点{if (graph[now.num][i] && !visit[i]){node next;next.num = i, next.step = now.step + 1; //更新选中点到根的距离visit[i] = 1;q.push(next);sum += value[i] * next.step; //该点的权重乘以与根的距离}}}return sum;
}int main()
{cin >> n;for (int i = 1; i <= n; i++){int w, u, v;cin >> w >> u >> v;value[i] = w;if (u != 0)graph[i][u] = graph[u][i] = 1;if (v != 0)graph[i][v] = graph[v][i] = 1;}int MinDis = INF;for (int i = 1; i <= n; i++){int tmp = BFS(i);if (tmp < MinDis)MinDis = tmp;}cout << MinDis << endl;
}

由于bfs每遍都是O(V+E)的,而这里特殊之处在于本身是个树,所以是n个节点和n-1条边

所以总复杂度近似为O(n^2).


七、【P3884】二叉树问题(Floyd算法)

树其实一种特殊的图。

即没有环路,一定联通,而且有且有只有一个节点没有入度的图。

  • 树上任意两点间的距离可以直接通过最短路算法获得。
  • 树的深度就是距离根节点最远的那个点的距离。
  • 树的宽度是节点最多的一层,同一层的节点距离根节点的距离都是相同的,所以也可以直接枚举获得。

AC代码:

Floyd:使用邻接矩阵存储树,先将邻接矩阵的对角线位置初始化为0(某点到自己的距离为0),其他位置初始化为INT_MAX/4(不相连的节点理论上距离为无限大,但是在计算是要考虑可能发生的溢出情况,所以除以4)

三层嵌套循环,列举每两个点 i 和 j 之间的距离,并且要考虑有中继点 k 存在的情况下,两点间的距离。(由于树是无环图,所以只需要一个中继点即可覆盖所有情况)

#include <iostream>
#include <string>
#include <algorithm>
#include <cmath>
#include <vector>
#include <map>
#include <cstring>
#include <queue>using namespace std;
const int INF = 0x7fffffff / 4; //若直接为INT_MAX,则使用floyed时会发生溢出int a[105][105] = { 0 };
int b[10005] = { 0 };void init()
{for (int i = 0; i < 105; i++){for (int j = 0; j < 105; j++){if (i != j)a[i][j] = INF;}}
}int main()
{init();int n;	cin >> n;for (int i = 1; i <= n - 1; i++){int u, v;	cin >> u >> v;a[u][v] = 1;a[v][u] = 2;}for (int k = 1; k <= n; k++){for (int i = 1; i <= n; i++){for (int j = 1; j <= n; j++){a[i][j] = min(a[i][j], a[i][k] + a[k][j]);}}}int maxdepth = 0;for (int i = 1; i <= n; i++){if (maxdepth < a[1][i])maxdepth = a[1][i];b[a[1][i]]++;}int maxd = 0;for (int i = 1; i <= maxdepth; i++){maxd = max(maxd, b[i]);}int u, v;cin >> u >> v;cout << maxdepth + 1 << endl;cout << maxd << endl;cout << a[u][v] << endl;
}

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

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

相关文章

Vue深入学习4—指令和生命周期

1.Vue是怎么识别 v- 指令的&#xff1f; 首先将HTML结构解析成属性列表&#xff0c;存入到数组中&#xff0c;接着遍历数组中的每一个节点&#xff0c;获取到不同指令对应的方法。 // 将HTML看作真正的属性列表 var ndoeAttrs node.attributes; var self this; // 类数组对象…

modbus poll测试工具测试modbus tcp与PLC设备连接使用方法

socket默认端口是502&#xff0c;socket连上之后&#xff0c; 按照modbuspoll工具设置的读写参数 生成的RTU命令格式去组装读PLC的设备数据 modbuspoll工具配置&#xff0c;以v9.9.2中文破解版为例&#xff1a; 首先点连接菜单&#xff08;connection&#xff09;建立连接&…

C#学习(十一)——Array和Collection

一、集合 集合重要且常用 孤立的数据是没有意义的&#xff0c;集合可以作为大量数据的处理&#xff0c;可进行数据的搜索、迭代、添加、删除。 C#中&#xff0c;所有集合都必须实现ICollection接口&#xff08;数组Array除外&#xff09; 集合说明Array数组&#xff0c;固定长…

消息中间件之八股面试回答篇:三、RabbitMQ如何解决消息堆积问题(100万条消息堆积)+RabbitMQ高可用性和强一致性机制+回答模板

RabbitMQ中的消息堆积问题 当生产者发送消息的速度超过了消费者处理消息的速度&#xff0c;就会导致队列中的消息堆积&#xff0c;直到队列存储消息达到上限。之后发送的消息就会成为死信&#xff0c;可能会被丢弃&#xff0c;这就是消息堆积问题。 解决消息堆积有三种种思路…

【Java Kubernates】Java调用kubernates提交Yaml到SparkOperator

背景 目前查询框架使用的是trino&#xff0c;但是trino也有其局限性&#xff0c;需要准备一个备用的查询框架。考虑使用spark&#xff0c;spark operator也已经部署到k8s&#xff0c;现在需要定向提交spark sql到k8s的sparkoperator上&#xff0c;使用k8s资源执行sql。 对比 …

LeetCode 40.组合总和 II

组合总和 II 给定一个候选人编号的集合 candidates 和一个目标数 target &#xff0c;找出 candidates 中所有可以使数字和为 target 的组合。 candidates 中的每个数字在每个组合中只能使用 一次 。 注意&#xff1a;解集不能包含重复的组合。 方法一、回溯 由于题目要求解集…

C语言第十一弹---函数(下)

​ ✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】 函数 1、嵌套调用和链式访问 1.1、嵌套调用 1.2、链式访问 2、函数的声明和定义 2.1、单个文件 2.2、多个文件 2.3、static 和 extern 2.3.1、static…

机器学习的数据库积累........

https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/tf1_detection_zoo.md ​​​​​​​ 另一个database:&#xff08;网址:Object Detection Made Easy with TensorFlow Hub: Tutorial&#xff09; Object Detection Made Easy with Ten…

菱形打印和十进制ip转二进制

1.菱形打印 用for循环 #!/bin/bashread -p "请输入菱形的大小:" num #打印向上的等腰三角形 for ((i=1;i<=num;i++)) dofor ((j=num-1;j>=i;j--))doecho -n " " #打印的是前面的空格donefor ((k=1;k<=2*i-1;k++))doecho -n "*" #打印…

蓝桥杯——每日一练(简单题)

题目 问题描述   123321是一个非常特殊的数&#xff0c;它从左边读和从右边读是一样的。   输入一个正整数n&#xff0c; 编程求所有这样的五位和六位十进制数&#xff0c;满足各位数字之和等于n 。 输入格式   输入一行&#xff0c;包含一个正整数n。 输出格式   按从…

基于vue实现待办清单案例

一、需求 新增内容&#xff1b; 删除内容&#xff1b; 统计操作&#xff1b; 清空数据。 示例图&#xff1a; 二、代码演示 1、基础准备 index.css代码 html, body {margin: 0;padding: 0; } body {background: #fff ; } button {margin: 0;padding: 0;border: 0;backgr…

C++ 隐式转换构造函数和explicit 关键字学习

据说在内核代码中,多个地方使用了explicit 关键字;下面看一下; 在 C++ 中,隐式转换构造函数指的是当我们将一种类型的值赋给该类对象时,编译器会自动调用相应的构造函数进行类型转换。这样可以使得不同类型之间能够互相赋值或者传参。 具体来说,当一个类有多个构造函数…

数据结构(1)--> 顺序表

定义&#xff1a; 顺序表存储定义&#xff1a; 把逻辑上相邻的数据元素存储在物理上相邻的存储单元中的存储结构&#xff0c;顺序表功能的实现借助于数组&#xff0c;通过对数组进行封装&#xff0c;从而实现增删查改的功能&#xff0c;严格意义上来说&#xff08;数组无法实现…

vue3+echarts绘制某省区县地图

vue3echarts绘制某省区县地图 工作中经常需要画各种各样的图&#xff0c;echarts是使用最多的工具&#xff0c;接近春节&#xff0c;想把之前画的echarts图做一个整合&#xff0c;方便同事和自己随时使用&#xff0c;因此用vue3专门写了个web项目&#xff0c;考虑之后不断完善…

STM正点mini-新建工程模板,GPIO及寄存器(介绍)

一.新建工程模板(基于固件库) 1.1库函数与寄存器的区别 这里的启动文件都是根据容量来进行区分的 对MDK而言即使include了&#xff0c;也不知道在哪里找头文件 STM32F10X_HD,USE_STDPERIPH_DRIVER 二.新建工程模板(基于寄存器) 上面的大部分配置与固件库的一样 具体可以看手…

第5章 (python深度学习——波斯美女)

第5章 深度学习用于计算机视觉 本章包括以下内容&#xff1a; 理解卷积神经网络&#xff08;convnet&#xff09; 使用数据增强来降低过拟合 使用预训练的卷积神经网络进行特征提取 微调预训练的卷积神经网络 将卷积神经网络学到的内容及其如何做出分类决策可视化 本章将…

【Linux】开始使用 vim 吧!!!

Linux 1 what is vim &#xff1f;2 vim基本概念3 vim的基本操作 &#xff01;3.1 vim的快捷方式3.1.1 复制与粘贴3.1.2 撤销与剪切3.1.3 字符操作 3.2 vim的光标操作3.3 vim的文件操作 总结Thanks♪(&#xff65;ω&#xff65;)&#xff89;感谢阅读下一篇文章见&#xff01;…

成熟的内外网数据交换方案,如何实现跨网传输?

网络迅速发展&#xff0c;我们可以从网络上查找到各式各样的信息&#xff0c;但是同时网络安全问题也随之严重。近几年&#xff0c;各种有关网络安全的新闻不断被报道&#xff0c;数据泄露给很多企业带来了严重打击&#xff0c;不仅是经济损失&#xff0c;严重者还会对企业的声…

SharedPreferences卡顿分析

SP的使用及存在的问题 SharedPreferences(以下简称SP)是Android本地存储的一种方式&#xff0c;是以key-value的形式存储在/data/data/项目包名/shared_prefs/sp_name.xml里&#xff0c;SP的使用示例及源码解析参见&#xff1a;Android本地存储之SharedPreferences源码解析。以…

STM32 PWM驱动设计

单片机学习&#xff01; 目录 文章目录 前言 一、PWM驱动配置步骤 二、代码示例及注意事项 2.1 RCC开启时钟 2.2 配置时基单元 2.3 配置输出比较单元 2.4 配置GPIO 2.5 运行控制 三、PWM周期和占空比计算 总结 前言 PWM本质是利用面积等效原理来改变波形的有效值。 一、PWM驱动…