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

map和set封装

创作中心-CSDN https://mpbeta.csdn.net/mp_blog/creation/editor/147238663

目录

创作中心-CSDNhttps://mpbeta.csdn.net/mp_blog/creation/editor/147238663

一、封装原理 

二、改造红黑树

三、实现迭代器

四、测试

五、小tip


一、封装原理 

上一篇文章我们完成了红黑树的模拟实现,现在我们要基于这个红黑树进行改造完成map和set的封装

这个是stl里面的红黑树原码 

这里面是map的原码 

这里面是set的原码 

 第一个模板参数通过观察我们可以发现是key,第二个模板参数map里面是pair结构,set里面是key

第二个模板参数决定了node中存什么

这样我们就不用实现两棵树了,我们通过第二个模板参数传什么来达到传到底是传key变成set还是派人变成map

二、改造红黑树

2.1初步改造

以下是模仿原码的红黑树的进行初步改造,具体是key还是value由传值传参决定

enum Color
{Red,Black
};
template<class T>
struct RBTreenode
{RBTreenode<T>* _left;RBTreenode<T>* _right;RBTreenode<T>* _parent;/*pair<K, V> _kv;*/Color _col;T _data;RBTreenode(const T& data):_left(nullptr), _right(nullptr), _parent(nullptr), _data(data), _col(Red){}
};
template<class K,class T>
class RBtree
{typedef RBTreenode<T> Node;
}
#pragma once
#include "RBTree.h"
namespace stn {template<class K>class set{private:RBtree<K, K> _t;};
}
#pragma once
#include "RBTree.h"
namespace stn {template<class K,class V>class map{private:RBtree<K, pair<K,V>> _t;};
}

2.2改造插入

	while (cur){if (cur->_kv.first < kv.first){parent = cur;cur = cur->_right;}else if (cur->_kv.first > kv.first){parent = cur;cur = cur->_left;}else{return false;}}

我们上一篇写的文章支持比较大小在这里就不管用了,如果他是set就支持比较,如果是pair这里就满足不了我们的需求

pair的比较规则是有一个小就小

	while (cur){if (cur->_data < data){parent = cur;cur = cur->_right;}else if (cur->_data > data){parent = cur;cur = cur->_left;}else{return false;}}

所以我们这里要写一个仿函数来支持它

	class set{public:struct SetKeyofT{const K& operator()(const K& key) {return key;}};private:RBtree<K, K, SetKeyofT> _t;};
	class map{public:struct MapKeyofT{const K& operator()(const pair<K,V>& kv) {return kv.first;}};private:RBtree<K, pair<K,V>,MapKeyofT> _t;};
template<class K,class T,class KeyofT>
class RBtree
{typedef RBTreenode<T> Node;
	KeyofT kot;while (cur){if (kot(cur->_data) < kot(data)){parent = cur;cur = cur->_right;}else if (kot(cur->_data) > kot(data)){parent = cur;cur = cur->_left;}else{return false;}}
	cur = new Node(data);cur->_col = Red;if (kot(parent->_data) < kot(data)){parent->_right = cur;cur->_parent = parent;}else{parent->_left = cur;cur->_parent = parent;}
bool Insert(const K& key)
{return _t.Insert(key);
}
	bool Insert(const pair<K,T>& kv){return _t.Insert(kv);}

这就是对插入的改造

三、实现迭代器

template<class T>
struct _TreeIterator
{typedef RBTreenode<T> Node;typedef _TreeIterator<T> iterator;Node* _node;_TreeIterator(Node* node):_node(node){}T& operator*(){return _node->_data;}T* operator->(){return &_node->_data;}};

3.1迭代器遍历

operator++我们应该如何遍历访问节点呢

比如it指向11,说明左子树已经访问完了,要访问右子树,下一个位置就应该是13

1.it指向的节点,右子树不为空,下一个就是右子树的最左节点

上面讨论的是右不为空的场景,接下来我们讨论右为空的场景比如说在1这个位置我们怎么访问到下一个位置

假设我们访问的是8这个位置8是7的右子树,根据中序来看,左根右,那么右子树完了父亲也完了,再看8这个位置属于2的右子树,接下来访问的就是11

假设我们访问的是5这个7的左子树位置的节点,此时访问完5了,但是7还没访问,那么下一个访问的就是根节点

2.it指向的节点,右子树为空,it中的节点所在的子树访问完了,往上找孩子是父亲左的那个祖先

就是比如说8这个节点,右子树一路访问完了,到2这个父亲左的节点,这个访问完了就应该访问它的父亲也就是8的祖先

	iterator begin(){Node* cur = _root;while (cur && cur->_left){cur = cur->_left;}return iterator(cur);}iterator end(){return iterator(nullptr);}

begin访问的是最左节点,end返回的是什么呢?我们来看15这个节点,15这个节点访问完了,向上返回,右树都访问完了,根据2规则,找孩子是父亲左的那个,但是我们访问到11的时候父亲为空,所以我们end应该是空节点

	Self& operator++(){//右不为空,找右树的最左节点;if (_node->_right){Node* cur = _node->_right;while (cur->_left){cur = cur->_left;}_node = cur;}else //右为空,找孩子是父亲左的节点{Node* cur = _node;Node* parent = cur->_parent;while (parent && cur == parent->_right){cur = parent;parent = parent->_parent;}_node = parent;}return *this;}
bool operator!=(const Self&s)
{return _node != s._node;
}
	typedef typename RBtree<K, pair<K, V>, MapKeyofT>::iterator iterator;iterator begin(){return _t.begin();}iterator end(){return _t.end();}
	typedef typename RBtree<K, K, SetKeyofT>::iterator iterator;iterator begin(){return _t.begin();}iterator end(){return _t.end();}

对类模板取内嵌类型,加typename告诉编译器这里是类型

3.2方括号补充

pair<iterator,bool> Insert(const T& data)
{if (_root == nullptr){_root = new Node(data);_root->_col = Black;return make_pair(iterator(_root),true);}Node* parent = nullptr;Node* cur = _root;KeyofT kot;while (cur){if (kot(cur->_data) < kot(data)){parent = cur;cur = cur->_right;}else if (kot(cur->_data) > kot(data)){parent = cur;cur = cur->_left;}else{return make_pair(iterator(cur), false);}}cur = new Node(data);Node* newnode = cur;cur->_col = Red;if (kot(parent->_data) < kot(data)){parent->_right = cur;cur->_parent = parent;}else{parent->_left = cur;cur->_parent = parent;}while (parent && parent->_col == Red){//      g//    p  u//  cNode* grandfather = parent->_parent;if (grandfather->_left == parent){Node* uncle = grandfather->_right;//叔叔存在且为红if (uncle && uncle->_col == Red){parent->_col = uncle->_col = Black;grandfather->_col = Red;cur = grandfather;parent = grandfather->_parent;}else{if (parent->_left == cur){//叔叔不存在或者叔叔存在且为黑RoRight(grandfather);parent->_col = Black;grandfather->_col = Red;}	//      g//    p  u//  celse{//叔叔不存在或者叔叔存在且为黑RoLeft(parent);RoRight(grandfather);cur->_col = Black;grandfather->_col = Red;}break;}}//      g//    u  p//       celse{Node* uncle = grandfather->_left;if (uncle && uncle->_col == Red){parent->_col = uncle->_col = Black;grandfather->_col = Red;cur = grandfather;parent = cur->_parent;}else{//      g//    u  p//       cif (parent->_right == cur){RoLeft(grandfather);grandfather->_col = Red;parent->_col = Black;}else{RoRight(parent);RoLeft(grandfather);grandfather->_col = Red;cur->_col = Black;}break;}}}_root->_col = Black;return make_pair(iterator(newnode), true);
}

如果我们要加入方括号就需要对插入进行改造

这里为什么用pair<iterator, bool> 呢,因为看我们下面这个代码我们要支持[]的话就必须针对返回类型进行改造,那我们用bool的话就拿不到这个迭代器指向的结点里面的value,如果key已存在,插入失败,返回对应位置的迭代器

最后一行插入newnode而不是cur的原因是cur可能会向上更新

这个是map的

		pair<iterator, bool> Insert(const pair<K, V>& kv){return _t.Insert(kv);}V& operator[](const K& key){//如果没有代表新插入一个节点pair<iterator, bool> ret = Insert(make_pair(key,V()));return ret.first->second;}

这个是set的

pair<iterator, bool> Insert(const K& key)
{return _t.Insert(key);
}

3.3const迭代器

因为这里几乎全部都要改造我就把大部分代码贴出来了

template<class T,class Ref,class Ptr>
struct _TreeIterator
{typedef RBTreenode<T> Node;typedef _TreeIterator<T,Ref,Ptr> Self;Node* _node;_TreeIterator(Node* node):_node(node){}Self& operator++(){//右不为空,找右树的最左节点;if (_node->_right){Node* cur = _node->_right;while (cur->_left){cur = cur->_left;}_node = cur;}else //右为空,找孩子是父亲左的节点{Node* cur = _node;Node* parent = cur->_parent;while (parent && cur == parent->_right){cur = parent;parent = parent->_parent;}_node = parent;}return *this;}Ref operator*(){return _node->_data;}Ptr operator->(){return &_node->_data;}bool operator!=(const Self&s){return _node != s._node;}
};
template<class K,class T,class KeyofT>
class RBtree
{typedef RBTreenode<T> Node;public:typedef _TreeIterator<T,T&,T*> iterator;typedef _TreeIterator<T,const T&,const T*> const_iterator;iterator begin(){Node* cur = _root;while (cur && cur->_left){cur = cur->_left;}return iterator(cur);}iterator end(){return iterator(nullptr);}const_iterator begin()const{Node* cur = _root;while (cur && cur->_left){cur = cur->_left;}return const_iterator(cur);}const_iterator end()const{return const_iterator(nullptr);}pair<Node*,bool> Insert(const T& data){if (_root == nullptr){_root = new Node(data);_root->_col = Black;return make_pair(_root,true);}Node* parent = nullptr;Node* cur = _root;KeyofT kot;while (cur){if (kot(cur->_data) < kot(data)){parent = cur;cur = cur->_right;}else if (kot(cur->_data) > kot(data)){parent = cur;cur = cur->_left;}else{return make_pair(cur, false);}}cur = new Node(data);Node* newnode = cur;cur->_col = Red;if (kot(parent->_data) < kot(data)){parent->_right = cur;cur->_parent = parent;}else{parent->_left = cur;cur->_parent = parent;}while (parent && parent->_col == Red){//      g//    p  u//  cNode* grandfather = parent->_parent;if (grandfather->_left == parent){Node* uncle = grandfather->_right;//叔叔存在且为红if (uncle && uncle->_col == Red){parent->_col = uncle->_col = Black;grandfather->_col = Red;cur = grandfather;parent = grandfather->_parent;}else{if (parent->_left == cur){//叔叔不存在或者叔叔存在且为黑RoRight(grandfather);parent->_col = Black;grandfather->_col = Red;}	//      g//    p  u//  celse{//叔叔不存在或者叔叔存在且为黑RoLeft(parent);RoRight(grandfather);cur->_col = Black;grandfather->_col = Red;}break;}}//      g//    u  p//       celse{Node* uncle = grandfather->_left;if (uncle && uncle->_col == Red){parent->_col = uncle->_col = Black;grandfather->_col = Red;cur = grandfather;parent = cur->_parent;}else{//      g//    u  p//       cif (parent->_right == cur){RoLeft(grandfather);grandfather->_col = Red;parent->_col = Black;}else{RoRight(parent);RoLeft(grandfather);grandfather->_col = Red;cur->_col = Black;}break;}}}_root->_col = Black;return make_pair(newnode, true);
}

这里面我们不用iterator的原因是用了一种巧妙的写法,因为我们iterator转化成const_iterator是无法转化的,如果要转化我们还要写再实现成复杂一点,有人说这里不是权限的缩小 吗,这是不一样的,const iterator 修饰的是这个指针不能改变,const_iterator修饰的指针指向的内容不能改变,这里其实都是两个类。

 

这里我们改用node*是因为pair可以根据不同的类型来初始化,因为你这个迭代器的本质实际上是一个结点,pair类型相同就是拷贝构造,类型不相同就是构造。

3.3.1set的const迭代器 

	typedef typename RBtree<K, K, SetKeyofT>::const_iterator iterator;typedef typename RBtree<K, K, SetKeyofT>::const_iterator const_iterator;iterator begin()const{return _t.begin();}iterator end()const {return _t.end();}

 因为set普通对象和const对象都不能被修改,所以普通对象和const对象我们都把它去调下面这个const版本。

typedef typename RBtree<K, pair<const K, V>, MapKeyofT>::iterator iterator;
typedef typename RBtree<K, pair<const K, V>, MapKeyofT>::const_iterator const_iterator;

至于map的迭代器,因为我们的value支持修改所以我们给它做普通迭代器和const迭代器,但是我们又期望key不被修改所以在类型那里加key

RBtree<K, pair<const K,V>,MapKeyofT> _t;

但是我们平常写插入的时候却没有写const

pair<iterator, bool> Insert(const pair<K, V>& kv)
{return _t.Insert(kv);
}

 得益于它是一层一层往下传的

K,去初始化const K,就用到了这个pair的这个构造 

四、测试
#include<map>
#include<set>
#include <string>
#include <iostream>
using namespace std;
#include "mymap.h"
#include "myset.h"
void test_set()
{stn::set<int> s;s.Insert(3);s.Insert(5);s.Insert(2);s.Insert(1);s.Insert(3);stn::set<int>::iterator it = s.begin();while (it != s.end()){cout << *it << " ";++it;}cout << endl;for (auto e : s){cout << e << " ";}
}
void test_map()
{stn::map<string, string> mp;mp.Insert(make_pair("sort", "排序"));mp.Insert(make_pair("left", "左边"));stn::map<string, string>::iterator it = mp.begin();while (it != mp.end()){cout << it->first << " "<<it->second<<" "<<endl;++it;}string arr[] = { "牛", "羊","猪", "狗", "牛", "牛", "狗", "羊", "猪", "猪", "狗", "猪", "牛" };stn::map<string, int> countMap;for (auto& e : arr){countMap[e]++;}for (auto& kv : countMap){cout << kv.first << ":" << kv.second << endl;}cout << endl;
}
int main()
{test_set();test_map();return 0;
}

五、小tip

有人会应该一样跟我疑虑那第一个模板参数是拿来干嘛的

T 在map中我们是传了模板pair<const K,V>

我们keyofT是不要,但是如果我们实现一个find函数的话就需要传这个K的类型;

这个你在用的时候传一个类型它会去找自己匹配的,然后比如说你在外面用解引用的时候它就会根据你的类型比如说要数据就是const T&来进行匹配

封装这里的弯弯绕绕还是非常多的,也是十分考验功底的,希望大家能借助这篇文章把自己不懂的搞明白 

相关文章:

map和set封装

创作中心-CSDNhttps://mpbeta.csdn.net/mp_blog/creation/editor/147238663 目录 创作中心-CSDNhttps://mpbeta.csdn.net/mp_blog/creation/editor/147238663 一、封装原理 二、改造红黑树 三、实现迭代器 四、测试 五、小tip 一、封装原理 上一篇文章我们完成了红黑…...

Java第六节:创建线程的其它三种方式(附带源代码)

作者往期文章 Java第五节&#xff1a;继承thread类创建线程-CSDN博客 一、实现Runnable接口 创建一个Thread02类实现Runnable接口 二、使用匿名内部类 在Main函数中匿名内部类创建线程 三、使用Lambda表达式 在Main函数中利用Lambda表达式创建一个线程 四、源代码 此项目源代…...

041-代码味道-大泥团模块

代码味道-大泥团模块 代码味道-Blob Module深度解析与C重构实践 一、Blob Module定义与特征 Blob Module&#xff08;大泥团模块&#xff09;是代码坏味道中的一种典型表现&#xff0c;指某个类或模块承担了过多不相关的职责&#xff0c;导致代码结构臃肿、可维护性差。其核心…...

强化学习系统学习路径与实践方法

一、学习路径规划​​ ​​1. 基础巩固阶段&#xff08;1-2个月&#xff09;​​ ​​必读教材​​&#xff1a; 《Reinforcement Learning: An Introduction》(Sutton & Barto) ​​第1-6章​​重点掌握&#xff1a;马尔可夫决策过程&#xff08;MDP&#xff09;、贝尔曼…...

CSS字体

CSS字体 CSS 中的字体样式设置是网页设计的重要部分&#xff0c;以下是一些关键知识点和常见用法&#xff1a; 1.font-family &#xff1a; 用于设置元素的字体系列。可以指定一个或多个字体名称作为备选项&#xff0c;以确保如果某个字体不可用&#xff0c;可以使用下一个备选…...

JDBC:数据库访问的原始接口

目录 一、JDBC 基础入门&#xff1a;数据库访问的原始接口 JDBC 是什么&#xff1f;它在 Java 中扮演什么角色&#xff1f; JDBC 工作原理图解&#xff08;驱动 -> 连接 -> 执行 -> 关闭&#xff09; 常见 JDBC 驱动类型及差异 第一个 JDBC 示例程序&#xff1a;连…...

使用 Electron 打包可执行文件和资源:完整实战教程

一.项目结构 项目结构建议如下&#xff1a; my-electron-app/ ├── example.exe ← 需打包的外部程序 ├── config.json ← 配置文件 ├── native-lib/ ← 自定义库或 DLL │ └── yourlib.dll ├── main.js …...

【网络安全】CI/CD 流水线漏洞

【网络安全】CI/CD 流水线漏洞 1. 保护您的软件管道&#xff1a;CI/CD 安全2. 什么是 CI/CD 以及它为何重要&#xff1f;2.1 持续集成&#xff08;CI&#xff09;&#xff1a;构建坚实的基础2.2 持续交付&#xff08;CD&#xff09;&#xff1a;准备发布2.3 持续部署&#xff0…...

计算机是如何工作的(上)

对于学习JavaEE初阶为什么要知道计算机是如何工作的&#xff0c;是因为在未来我们写代码的时候&#xff0c;会出现一些bug&#xff0c;而在代码层面是看不出来的&#xff0c;所以我们需要了解一些关于计算机内部是如何工作的&#xff0c;从而提高代码的健壮度。 计算机的组成&…...

【SF顺丰】顺丰开放平台API对接(Java对接篇)

对接前置篇&#xff1a; 【SF顺丰】顺丰开放平台API对接&#xff08;注册、API测试篇&#xff09;_顺丰api接口对接指南-CSDN博客 1.实现效果展示 2.SF顺丰开放平台&#xff0c;JDK资源下载。 下载地址&#xff1a;顺丰开放平台 3.将下载的JDK放入项目中。 4.将JDK资源引入p…...

【KWDB创作者计划】_针对KWDB时序数据库(多副本集群环境)进行压力测试

【KWDB创作者计划】_针对KWDB时序数据库&#xff08;多副本集群环境&#xff09;进行压力测试 1. 概述2. 压测环境部署3. 生成测试数据4. 写入性能测试5. 查询性能测试7. 总结 1. 概述 KWDB是一款主要应用于工业物联网、数字能源、车联网、智慧产业等领域的时序数据库&#xff…...

24.中医知识问答删除历史对话功能前端代码实现

前端实现对话删除功能的完整指南 功能概述 前篇文章介绍了删除历史对话的后端开发&#xff0c;本篇将介绍如何在前端实现一个完整的对话删除功能&#xff0c;包括用户确认、API调用、状态管理和错误处理等关键环节。 功能拆解 1. 用户确认机制 javascript const confirmDe…...

在Cursor编辑器上部署MCP(Minecraft Coder Pack)完整指南

MCP&#xff08;Minecraft Coder Pack&#xff09;是用于反编译和修改Minecraft Java版代码的工具包。本教程将详细介绍如何在Cursor编辑器中配置和运行MCP&#xff0c;以便高效地进行Minecraft模组开发或代码研究。 1. 准备工作 1.1 所需工具 Cursor编辑器&#xff08;基于VS…...

STM32——相关软件安装

本文是根据江协科技提供的教学视频所写&#xff0c;旨在便于日后复习&#xff0c;同时供学习嵌入式的朋友们参考&#xff0c;文中涉及到的所有资料也均来源于江协科技&#xff08;资料下载&#xff09;。 Keil5 MDK安装 1.安装Keil5 MDK2.安装器件支持包方法一&#xff1a;离线…...

蓝牙WiFi模组rtl8821cs在Android14调

环境 SDK: AOSP14 主控&#xff1a;RK3576 蓝牙&#xff1a;RTL8821CS 先记一下官网文档关于蓝牙的资料 蓝牙 | Android Open Source Project 还在调&#xff0c;先看看啥情况&#xff0c;点赞多或者想起来记录再回来 TODO...

MCP实践第一步--磕磕碰碰搭环境

由于deepseek-r1不支持function calling&#xff0c;所以我们采用了deepseek-v3进行实践&#xff0c;模型名称为deepseek-chat&#xff0c;在deepseek官网获取api-key。 一、参照MCP官网设置环境 创建项目目录 uv init mcp-client # 若没有uv&#xff0c;则先通过pip instal…...

Java并发:线程池

目录 一、核心概念与设计原理 1、线程池的核心价值 2、核心接口和类 3、线程池的核心构造参数 4、线程池工作流程 二、参数选择 1、任务队列选择 2、拒绝策略选择 3、常见线程池选择 4、参数调优 三、 应用 1、创建建议 2、生命周期管理&#xff1a;优雅关闭 3、…...

Kubernetes集群超配节点容量

目录&#xff1a; 1、节点超配简介2、创建 PriorityClass3、运行请求节点容量的 Pod4、调整占位资源请求5、设置所需的副本数量6、自动扩缩容组件6.1、手动方式6.2、自动方式 1、节点超配简介 节点超配是一种主动预留部分集群计算资源的策略。这种预留有助于减少在扩缩容事件期…...

每日一题(小白)回溯篇7

首先我们可以判断出这是一个dfs的题目&#xff0c;因为简言之就是要求最短路径。其次这个题目与直接找最短路径有所不同&#xff0c;增加了条件必须依次穿过指定的符号。无论坦克走到任何一点都有四个方向可以走&#xff08;越界要判断&#xff09;&#xff0c;结束的条件是到达…...

rk3588上完成halcon的形状模型配准以及和opencv的图像转换

一、准备工作 1&#xff09;安装好halcon&#xff0c;确保halcon的c的调用是正常的 2&#xff09;编译好opencv 上面的两个步骤&#xff0c;均可以参考我的两个博文完成&#xff1a; Halcon在linux及ARM上的安装及c工程化_halcon linux-CSDN博客 RK3588上编译opencv 及基于…...

Spring Boot 断点续传实战:大文件上传不再怕网络中断

精心整理了最新的面试资料和简历模板&#xff0c;有需要的可以自行获取 点击前往百度网盘获取 点击前往夸克网盘获取 一、痛点与挑战 在网络传输大文件&#xff08;如视频、数据集、设计稿&#xff09;时&#xff0c;常面临&#xff1a; 上传中途网络中断需重新开始服务器内…...

Springboot集成websocket实现消息推送

假设有个需求需要多个用户同时在对应的消息面板实时查看相关接口的执行流程进度&#xff0c;此时可以可考虑使用websocket来实现结果进度推送 一、引入websocket依赖&#xff0c;并编写WebSocket配置类 <dependency><groupId>org.springframework.boot</group…...

PostgreSQL 用户资源管理

PostgreSQL 用户资源管理 PostgreSQL 提供了多种机制来管理和限制用户对数据库资源的使用&#xff0c;以下是全面的资源管理方法&#xff1a; 1 连接限制 1.1 限制最大连接数 -- 在 postgresql.conf 中设置 max_connections 100 -- 全局最大连接数-- 为特定用户设置连接限…...

Uniapp:pages.json页面路由

目录 一、pages二、style 一、pages uni-app 通过 pages 节点配置应用由哪些页面组成&#xff0c;pages 节点接收一个数组&#xff0c;数组每个项都是一个对象&#xff0c;其属性值如下&#xff1a; 属性类型默认值描述pathString配置页面路径styleObject配置页面窗口表现nee…...

使用open3d将pcd点云按照颜色等级分块显示并令其随颜色变化播放

👑主页:吾名招财 👓简介:工科学硕,研究方向机器视觉,爱好较广泛… ​💫签名:面朝大海,春暖花开! 使用open3d将pcd点云按照颜色等级分块显示并令其随颜色变化播放 引言显示效果点云获取完整代码引言 有很多时候我们需要更改pcd点云某些区域的颜色,可能是颜色随着点…...

玩转Docker | 使用Docker部署nullboard任务管理工具

玩转Docker | 使用Docker部署nullboard任务管理工具 前言一、nullboard介绍简介主要特点二、系统要求环境要求环境检查Docker版本检查检查操作系统版本三、部署nullboard服务下载镜像创建容器创建容器检查容器状态检查服务端口安全设置四、访问nullboard服务访问nullboard首页五…...

如何避免流程形式化导致的效率低下?

要避免流程形式化导致的效率低下&#xff0c;核心在于&#xff1a;聚焦流程价值、保障执行灵活性、优化流程设计、建立反馈机制、提升执行感知。其中&#xff0c;聚焦流程价值 是解决流程“空转”的首要原则。流程不应只是文档或制度的堆叠&#xff0c;而要服务于业务目标&…...

Java学习手册:HTTP 协议基础知识

一、HTTP 协议概述 HTTP&#xff08;HyperText Transfer Protocol&#xff09;即超文本传输协议&#xff0c;是用于从万维网&#xff08;WWW&#xff1a;World Wide Web &#xff09;服务器传输超文本到本地浏览器的传输协议。它是一个应用层协议&#xff0c;基于请求-响应模型…...

基于多模态融合算法的航空武器毁伤评估技术方案

基于多模态融合算法的航空武器毁伤评估技术方案 1. 引言 航空武器毁伤评估(Damage Assessment, DA)是现代战争中的关键环节,直接影响后续作战决策。传统的人工评估方式效率低、主观性强,且在高强度战场环境下难以实时完成。因此,本研究提出一种基于多模态融合算法的自动…...

欧拉-国产操作系统替代产品如何

欧拉(openEuler)国产操作系统是由华为发起并联合开源社区共同开发的企业级操作系统,旨在构建自主可控的数字基础设施生态底座。以下从开发背景、技术特点、应用场景、生态建设及市场表现等方面进行全面介绍: 一、开发背景与战略定位 国家需求驱动 在中美技术竞争背景下,国…...

入门-C编程基础部分:16、 预处理器

飞书文档https://x509p6c8to.feishu.cn/wiki/DzSJwsGiTiXkeCkyEYUcuXbKnbf C 预处理是编译过程中一个单独的步骤&#xff0c;是一个文本替换工具而已。所有的预处理命令都是以井号&#xff08;#&#xff09;开头。 指令描述#define定义宏#ifdef如果宏已经定义&#xff0c;则返…...

Spark-SQL4

一 .Spark-SQL核心编程&#xff08;六&#xff09; Spark-SQL连接Hive Apache Hive 是 Hadoop 上的 SQL 引擎&#xff0c;Spark SQL 编译时可以包含 Hive 支持&#xff0c;也可以不包含。包含 Hive 支持的 Spark SQL 可以支持 Hive 表访问、UDF (用户自定义函数)、Hive 查询语…...

模数转换【1】AD7699

1.开发背景 一款可以模数转换芯片&#xff0c;兼容通用 SPI 接口&#xff0c;支持最多支持 8 个通道和 500KSPS 的采样率。支持单个通道采集和扫描采集模式。 同系列的芯片还有 AD7682 和 AD7689 等。 2.开发需求 配置内部参考电压4.096V&#xff0c;实现单个通道采集和扫描采集…...

P5670 秘籍-反复异或 Solution

Description 给定序列 a ( a 1 , a 2 , ⋯ , a n ) a(a_1,a_2,\cdots,a_n) a(a1​,a2​,⋯,an​) 和常数 m m m&#xff0c;有 q q q 个操作分两种&#xff1a; add ⁡ ( l , r , x ) \operatorname{add}(l,r,x) add(l,r,x)&#xff1a;对每个 i ∈ [ l , r ] i\in[l,r] …...

PID控制程序编写

目录 一、C语言PID控制器示例代码 二、代码解释 三、重要注意事项 一、C语言PID控制器示例代码 #include <stdio.h> #include <stdlib.h> #include <unistd.h> // For sleep function typedef struct { double Kp; // 比例增益 double…...

推荐系统/业务,相关知识/概念2

一、漫画库更新大量新作品&#xff0c;如何融入推荐系统&#xff1f; 参考答案&#xff1a; 快速提取新作品特征&#xff1a;除基础属性外&#xff0c;利用自然语言处理技术提取漫画简介关键词等丰富特征向量&#xff0c;分析情节、角色设定等深层次特征结合物品画像体系分类…...

基于Python的施工图与竣工图对比小工具开发方案

基于Python的施工图与竣工图对比小工具开发方案 一、引言 在工程建设领域&#xff0c;施工图与竣工图的对比是项目验收的关键环节。传统人工对比方式效率低、易出错&#xff0c;本文基于Python开发一款自动化对比工具&#xff0c;支持快速检测图纸差异并生成可视化报告&#x…...

2025年世界职业院校技能大赛实施方案(意见稿)

为贯彻落实《教育强国建设规划纲要&#xff08;2024—2035年&#xff09;》&#xff0c;进一步提升世界职业院校技能大赛&#xff08;以下简称“大赛”&#xff09;内涵质量&#xff0c;发挥大赛引领作用&#xff0c;提升高技能人才培养质量&#xff0c;服务现代职业教育体系建…...

辛格迪客户案例 | 苏州富士莱医药GMP培训管理(TMS)项目

一、案例概述 富士莱医药股份有限公司位于美丽的江南水乡常熟&#xff0c;前身为常熟富士莱医药化工有限公司&#xff0c;从建厂初期面积仅有10余亩&#xff0c;逐步扩展到100余亩。近年来公司飞速发展&#xff0c;以黑马姿态发展成为中国专业生产硫辛酸系列产品、肌肽系列产品…...

安恒安全渗透面试题

《网安面试指南》https://mp.weixin.qq.com/s/RIVYDmxI9g_TgGrpbdDKtA?token1860256701&langzh_CN 5000篇网安资料库https://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247486065&idx2&snb30ade8200e842743339d428f414475e&chksmc0e4732df793fa3bf39…...

【基于WSAAsyncSelec模型的通信程序设计】

文章目录 一、实验背景与目的二、实验设计与实现思路1. 设计思想2. 核心代码实现 总结 一、实验背景与目的 这次实验主要是为了让大家了解基于 WSAAsyncSelect 模型通信程序的编写、编译和执行过程。通过实践操作&#xff0c;深入掌握这种模型在实现计算机之间通信时的应用。 …...

Spring Boot+Mybatis设置sql日志打印

Spring BootMybatis设置sql日志打印 在全局配置文件添加以下内容&#xff1a;logging.level.com.demo.mapperdebug&#xff0c;com.demo.mapper&#xff1a;src下的mapper路径&#xff0c;debug&#xff1a;设置日志打印级别为debug&#xff0c;亦可设置为&#xff1a;ERROR、…...

Java 性能优化:从硬件到软件的全方位思考

Java 性能优化&#xff1a;从硬件到软件的全方位思考 在数字化飞速发展的当下&#xff0c;Java 作为广泛使用的编程语言&#xff0c;在各个应用领域发挥着关键作用。而 Java 性能优化作为提升系统运行效率、降低成本的核心环节&#xff0c;需要我们从硬件到软件进行全方位深入…...

ros2 humble moveit调试笔记

Overview — ROS2 Grasp Library Tutorials 0.5.0 documentation Robot Interface — ROS2 Grasp Library Tutorials 0.5.0 documentation 手动添加ompl_planning.yaml文件 planning_plugins:- ompl_interface/OMPLPlanner # To optionally use Ruckig for jerk-limited s…...

静态点亮数码管的某几段(STC89C52单片机)

#include <reg52.h> sbit ADDR0 P1^0; sbit ADDR1 P1^1; sbit ADDR2 P1^2; sbit ADDR3 P1^3; sbit ENLED P1^4; void main() { ENLED 0; //使能U3&#xff0c;选择数码管DS1 ADDR3 1; ADDR2 0; ADDR1 0; ADDR0 0; P0 0xF9; /…...

搭建哨兵架构

Redis大纲 3.1.sentinel环境准备&#xff1a; a.3个sentinel实例信息&#xff1a; 1.sentinel实例信息如下&#xff0c;sentinel只是起到监控作用&#xff0c;不存放数据&#xff01;&#xff01;2.为了节省资源&#xff0c;在同一台虚拟机开启3个实例&#xff0c;必须准备三…...

阿里云入门手册

阿里云入门手册 一、付费方式二、云计算基础概念&#xff08;一&#xff09;云计算定义&#xff08;二&#xff09;云计算优势&#xff08;三&#xff09;云计算部署模式&#xff08;四&#xff09;专有网络 VPC 三、阿里云ECS实例&#xff08;一&#xff09;实例类型&#xff…...

AI日报 - 2024年04月22日

&#x1f31f; 今日概览(60秒速览) ▎&#x1f916; 模型进展 | Google发布Gemini 2.5 Flash&#xff0c;强调低延迟与成本效益&#xff1b;Kling AI 2.0展示多轴运动视频生成&#xff1b;研究揭示SLM在知识图谱上优于LLM&#xff0c;RLHF在推理提升上存局限。 ▎&#x1f4bc;…...

Windows BilibiliHistoryFetcher-v1.3.2-v1.2.1-开源B站历史记录管理工具[支持批量管理下载]

Windows BilibiliHistoryFetcher 链接&#xff1a;https://pan.xunlei.com/s/VOONAVJpANYPmzu1Zc3B0q1XA1?pwdnrjc# 使用说明&#xff1a; 以1.3.2与1.2.1版本为例 需要下载 BiliBili-History-Frontend 前端程序&#xff0c;在下载 BilibiliHistoryAnalyzer 解压运行&#…...

CH585单片机的LCD外设怎么驱动段式LCD

1、首先这里只讲应用&#xff0c;不讲具体原理。 要驱动段式LCD&#xff0c;这里就要知道占空比的调整&#xff0c;比如1/4为例就需要4个COM口。这4个COM口由单片机自行驱动&#xff0c;你不用管。就像硬件IIC和SPI&#xff0c;时序问题不用你去操心&#xff0c;你要做的就是向…...