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

从哈希桶角度看 unordered_map 与 unordered_set 的实现

文章目录

  • 一、引言
  • 二、C++ unordered系列的无序关联式容器概览
  • 三、基于哈希桶的C++ unordered系列数据结构模拟实现
    • 1、unordered_map的模拟实现
    • 2、unordered_set的模拟实现
    • 3、哈希桶及其迭代器实现的代码
  • 四、扩展与应用
    • 1. 自定义哈希函数
    • 2. 其他unordered数据结构
      • unordered_multimap与unordered_map
      • unordered_multiset与unordered_set
    • 3. 实际应用案例分析

一、引言

哈希函数与哈希桶是计算机科学中用于实现高效数据检索的重要工具。在之前的博客中,我们已经详细探讨了哈希的基本概念、哈希函数的构造方法以及哈希桶的工作原理等内容。在本篇博客中,我们将进一步深入探索C++中的unordered系列数据结构,并利用之前介绍的哈希桶原理进行模拟实现。

C++11提供的unordered系列数据结构,如unordered_mapunordered_set等,是STL(Standard Template Library)中提供的一组非常重要的容器。它们以哈希表为基础,通过哈希函数将键映射到存储位置,从而实现了快速的插入、删除和查找操作。这些数据结构在处理大规模数据时,能够展现出比有序容器(如map、set)更高的性能。在C++11中,提供了的4个unordered系列的关联式容器。这四个容器与红黑树结构的关联式容器使用方式基本类似,只是其底层结构不同。

本文将使用哈希桶对C++ unordered系列数据结构进行模拟实现。文本前置内容,请点击此处: 哈希技术解析:从哈希函数到哈希桶迭代器的全面指南


二、C++ unordered系列的无序关联式容器概览

1. unordered_map与unordered_multimap简介

数据结构特性:

  • unordered_map:C++ STL中的一个无序关联容器,它存储的元素是键值对,并且每个键在容器中唯一。其内部实现通常基于哈希表,通过哈希函数将键映射到存储位置,从而提供了常数时间复杂度的插入、删除和查找操作。
  • unordered_multimap:与unordered_map类似,但它允许键在容器中出现多次,即可以存储多个具有相同键的键值对。

应用场景:

  • unordered_map:当需要快速根据键查找对应的值时,或者当键的唯一性很重要时,unordered_map是一个很好的选择。例如,在缓存系统、词频统计等场景中,unordered_map可以高效地存储和检索键值对。
  • unordered_multimap:当需要存储多个具有相同键的键值对时,可以使用unordered_multimap。这在某些特定的应用场景中很有用,比如记录一个单词在文本中出现的所有位置。

2. unordered_set与unordered_multiset简介

数据结构特性:

  • unordered_set:是一个无序集合,它存储的元素是唯一的,不包含重复的元素。其内部实现也基于哈希表,通过哈希函数将元素映射到存储位置,从而实现了常数时间复杂度的插入、删除和查找操作。
  • unordered_multiset:与unordered_set类似,但它允许集合中包含重复的元素。

应用场景:

  • unordered_set:当需要快速检查一个元素是否存在于集合中,或者需要维护一个不包含重复元素的集合时,unordered_set是一个合适的选择。例如,在算法中去除重复元素、实现并集和交集运算等场景,unordered_set都能提供高效的解决方案。
  • unordered_multiset:当需要统计元素的出现次数或者需要维护一个包含重复元素的集合时,可以使用unordered_multiset。这在某些特定的数据处理和分析任务中可能会很有用。

总的来说,C++的unordered系列数据结构提供了高效的无序存储和检索机制,适用于各种需要快速处理大量数据的场景。通过合理地选择和使用这些数据结构,可以显著提高程序的性能和效率。

非unordered系列数据结构点击此处:深入解析C++树形关联式容器:map、set及其衍生容器的使用与原理-CSDN博客


三、基于哈希桶的C++ unordered系列数据结构模拟实现

1、unordered_map的模拟实现

  • 使用自定义哈希桶存储键值对

    unordered_map的简化模板类定义(注:hash_bucket是我实现的哈希桶所在的命名空间) :

    template<class K, class V, class Hash = HashFunc<K>>
    class unordered_map
    {struct MapKeyOfT {const K& operator()(const pair<K, V>& kv) { return kv.first; }};
    public:typedef typename hash_bucket::HashTable<K, pair<const K, V>, MapKeyOfT, Hash>::iterator iterator;// .... 
    private:hash_bucket::HashTable<K, pair<const K, V>, MapKeyOfT, Hash> _ht;
    };
    

    模板参数K:键(Key)的类型。V:值(Value)的类型。Hash:哈希函数(Hash Function)的类型,默认为HashFunc<K>,即默认以K来计算哈希位置。该参数也在哈希桶部分有介绍。

    内部结构体 MapKeyOfT:这个结构体定义了一个调用运算符,用于从pair<K, V>中提取键。这是哈希表内部可能需要的,以便能够根据键来定位存储的元素。

    迭代器类型定义typedef语句定义了一个迭代器类型,表示指向hash_bucket::HashTable中元素的迭代器。这个迭代器类型用于公开unordered_map的接口,以便用户可以遍历集合中的元素。

    私有成员_htunordered_map的私有成员,其类型为hash_bucket::HashTable<K, pair<const K, V>, MapKeyOfT, Hash> 。这个哈希表用于存储键值对,并根据键的哈希值来定位元素。

  • 实现插入、查找、删除等基本操作

    operator[]用于访问或插入一个键值对。如果键k已经存在于unordered_map中,则该函数返回该键对应的值的引用;如果键k不存在,则该函数插入一个新的键值对(键为k,值为V()的默认构造实例),并返回新插入值的引用:

    V& operator[](const K& k) {pair<iterator, bool> it = insert({ k,V() });return (*it.first).second;//return (*((this->insert(make_pair(k, V()))).first)).second;
    }
    

    在这段代码中,insert成员函数被调用,它尝试插入一个键值对到unordered_map中。insert返回一个pair<iterator, bool>,其中迭代器指向新插入的元素(或已存在的元素),布尔值表示是否实际插入了新元素。由于unordered_map不允许重复的键,所以对于operator[]来说,这个布尔值总是true,除非在插入过程中发生了异常。然后,通过解引用迭代器it.first来获取键值对的引用,并返回其second成员(即值)的引用。

    pair<iterator,bool> insert(const pair<K, V>& kv) { return _ht.Insert(kv); }  
    bool erase(const K& k) { return _ht.Erase(k); }  
    iterator find(const K& k) { return _ht.Find(k); }
    
    • insert函数接收一个pair<K, V>类型的参数,并调用_ht.Insert方法尝试将其插入哈希表中。它返回一个pair<iterator, bool>,其中迭代器指向新插入的元素(或已存在的元素),布尔值表示是否成功插入了新元素。
    • erase函数接收一个键类型的参数,并调用_ht.Erase方法尝试从哈希表中删除具有该键的键值对。它返回一个布尔值,表示删除操作是否成功。
    • find函数接收一个键类型的参数,并调用_ht.Find方法查找具有该键的键值对。如果找到,它返回一个指向该键值对的迭代器;否则,返回end()迭代器。
  • 封装哈希桶迭代器

    我们的哈希桶已实现了绝大部分的功能,因此我们此处仅仅调用其函数即可。

    typedef typename hash_bucket::HashTable<K, pair<const K, V>, MapKeyOfT, Hash>::iterator iterator;	
    iterator begin() { return _ht.begin(); }
    iterator end() { return _ht.end(); }
    

2、unordered_set的模拟实现

  • 利用哈希桶存储唯一元素

    unordered_set的简化模板类定义(注:hash_bucket是我实现的哈希桶所在的命名空间) :

    template<class K, class Hash = HashFunc<K>>
    class unordered_set{struct SetKeyOfT{const K& operator()(const K& key) { return key; }};
    public:typedef typename hash_bucket::HashTable<K, const K, SetKeyOfT, Hash>::iterator iterator;//...
    private:hash_bucket::HashTable<K, const K, SetKeyOfT, Hash> _ht;
    };
    

    模板参数unordered_set模板接受两个类型参数,KHashK是集合中元素的键类型,Hash是哈希函数类型,用于计算键的哈希值。默认情况下,如果没有提供Hash,它将使用HashFunc<K>作为哈希函数。

    内部结构体SetKeyOfT:这是一个简单的函数对象(或称为仿函数),它重载了operator()以返回其输入的引用。在unordered_set的上下文中,它用于从键中提取键本身(在这种情况下,键就是元素本身)。这是为了与hash_bucket::HashTable的接口保持一致,该接口可能期望一个可以从某种类型中提取键的函数对象。

    迭代器类型定义:使用typedef语句定义了一个名为iterator的类型别名,它表示指向hash_bucket::HashTable中元素的迭代器。这个迭代器类型用于公开unordered_set的接口,以便用户可以遍历集合中的元素。

    私有成员变量_htunordered_set的一个私有成员变量,其类型为hash_bucket::HashTable<K, const K, SetKeyOfT, Hash>。这表示它是一个哈希表,用于存储unordered_set中的元素。键类型是const K,因为集合中的元素不应被修改(在unordered_set中,元素是唯一的,并且一旦插入就不能被修改)。SetKeyOfT用于从键中提取键,而Hash是用于计算哈希值的函数。

  • 实现集合的基本操作

    pair<iterator,bool> insert(const K& k) { return _ht.Insert(k); }
    bool erase(const K& k) { return _ht.Erase(k); }
    iterator find(const K& k) { return _ht.Find(k); }
    
    • insert函数尝试在集合中插入一个元素,并返回一个pair<iterator, bool>,其中迭代器指向新插入的元素(或已存在的元素),布尔值表示是否实际插入了新元素。由于unordered_set不允许重复元素,所以如果尝试插入一个已经存在的元素,该函数不会插入新元素,而是返回指向已存在元素的迭代器,并将布尔值设置为false
  • 封装哈希桶迭代器

    此处与unordered_map相同。

    typedef typename hash_bucket::HashTable<K, const K, SetKeyOfT, Hash>::iterator iterator;
    iterator begin() { return _ht.begin(); }
    iterator end() { return _ht.end(); }
    

3、哈希桶及其迭代器实现的代码

该文已详细叙述哈希桶相关内容 ->深入解析C++树形关联式容器:map、set及其衍生容器的使用与原理-CSDN博客

template<class K>
struct HashFunc {size_t operator()(const K& key) { return (size_t)key; }
};
template<>
struct HashFunc<string> {size_t operator()(const string& s) {size_t hashi = 0;for (auto& e : s) {hashi += e;hashi *= 31;}return hashi;}
};
namespace hash_bucket
{template<class T>struct HashNode {HashNode<T>* _next;T _data;HashNode(const T& data) :_next(nullptr), _data(data) {}};template<class K, class T, class KeyOfT, class Hash >class HashTable;template<class K, class T, class KeyOfT, class Hash>struct  __HTIterator {typedef HashNode<T> Node;typedef HashTable<K, T, KeyOfT, Hash> HT;typedef __HTIterator<K, T, KeyOfT, Hash> Self;Node* _node;HT* _ht;__HTIterator(Node* node, HT* ht) :_node(node), _ht(ht) {}T& operator*() { return _node->_data; }T* operator->() { return &_node->_data; }bool operator!=(const Self& s)const { return _node != s._node; }bool operator==(const Self& s) const { return _node == s._node; }Self& operator++() {if (_node->_next) {_node = _node->_next;}else {KeyOfT kot;Hash hs;size_t hashi = hs(kot(_node->_data)) % _ht->_tables.size();hashi++;while (hashi < _ht->_tables.size()) {if (_ht->_tables[hashi]) {_node = _ht->_tables[hashi];break;}hashi++;}if (hashi == _ht->_tables.size()) {_node = nullptr;}}return *this;}};template<class K, class T, class KeyOfT, class Hash >class HashTable {typedef HashNode<T> Node;template<class K, class T, class KeyOfT, class Hash>friend struct __HTIterator;public:typedef __HTIterator<K, T, KeyOfT, Hash> iterator;iterator begin(){for (size_t i = 0; i < _tables.size(); i++)if (_tables[i])return iterator(_tables[i], this);return end();}iterator end() { return iterator(nullptr, this); }HashTable()//:kot(KeyOfT()),hs(Hash()){_tables.resize(10, nullptr);_n = 0;kot = KeyOfT();hs = Hash();} ~HashTable() {for (size_t i = 0; i < _tables.size(); i++) {Node* cur = _tables[i];while (cur) {Node* next = cur->_next;delete cur;cur = next;}_tables[i] = nullptr;}}pair<iterator,bool> Insert(const T& data) {iterator it = Find(kot(data));if (it != end())return { it,false};if (_n == _tables.size()) {vector<Node*> newTables(_tables.size() * 2, nullptr);for (size_t i = 0; i < _tables.size(); i++){Node* cur = _tables[i];while (cur) {Node* next = cur->_next;size_t hashi = hs(kot(cur->_data)) % newTables.size();cur->_next = newTables[hashi];newTables[hashi] = cur;cur = next;}_tables[i] = nullptr;}_tables.swap(newTables);}size_t hashi = hs(kot(data)) % _tables.size();Node* newnode = new Node(data);newnode->_next = _tables[hashi];_tables[hashi] = newnode;++_n;return { iterator(newnode, this),true };}bool Erase(const K& key) {size_t hashi = hs(key) % _tables.size();Node* prev = nullptr;Node* cur = _tables[hashi];while (cur) {if (kot(cur->_data) == key) {// 删除if (prev)prev->_next = cur->_next;else_tables[hashi] = cur->_next;delete cur;--_n;return true;}prev = cur;cur = cur->_next;}return false;}iterator Find(const K& key) {size_t hashi = hs(key) % _tables.size();Node* cur = _tables[hashi];while (cur) {if (kot(cur->_data) == key)return iterator(cur, this);cur = cur->_next;}return iterator(nullptr, this);}private:vector<Node*> _tables;size_t _n;KeyOfT kot; Hash hs;};
}

四、扩展与应用

1. 自定义哈希函数

在C++中,当使用std::unordered_setstd::unordered_map等无序容器时,哈希函数起着至关重要的作用。默认的哈希函数对于许多类型都工作得很好,但有时对于自定义类型或特殊需求,默认的哈希函数可能不是最优的,甚至可能导致性能下降或哈希冲突过多。

为特定类型设计哈希函数

对于自定义类型,需要提供一个哈希函数,该函数接受自定义类型的对象作为参数,并返回一个足够大的整数值。设计哈希函数时,需要确保:

  • 不同的对象尽可能映射到不同的哈希值。
  • 相同的对象总是映射到相同的哈希值。
  • 哈希函数的计算应该尽可能快。

例如,对于一个包含字符串和整数的自定义类型,可以使用字符串的哈希值和整数的哈希值的组合作为整体的哈希值。

2. 其他unordered数据结构

除了unordered_setunordered_map之外,标准库还提供了unordered_multimapunordered_multiset。这两个数据结构分别允许存储具有相同键的多个值对和多个值。

unordered_multimap与unordered_map

unordered_multixxxunordered_xxx的主要区别在于前者允许键重复,而后者不允许。具体来说:

  • 键的重复性unordered_map中的每个键都是唯一的,每个键只能映射到一个值。而unordered_multimap允许键的重复,这意味着同一个键可以映射到多个值。
  • 使用场景:当你需要存储键值对,并且每个键只对应一个值时,unordered_map是合适的选择。而如果你需要存储的键值对中有多个键是相同的,并且每个键对应多个值,那么unordered_multimap更为合适。
  • 内部实现:两者都使用哈希表作为底层数据结构,以实现快速的插入、删除和查找操作。但由于unordered_multimap允许键重复,因此在处理冲突和存储键值对时可能需要更复杂的逻辑。

unordered_multiset与unordered_set

  • 元素的重复性unordered_set中的每个元素都是唯一的,不允许有重复元素。而unordered_multiset则允许元素重复,即集合中可以包含多个相同的元素。
  • 使用场景:当你需要存储一个不包含重复元素的集合时,unordered_set是合适的选择。而如果你需要存储的集合中可能包含重复的元素,那么unordered_multiset更为合适。
  • 内部实现:两者都使用哈希表作为底层数据结构,以实现快速的插入、删除和查找操作。但由于unordered_multiset允许元素重复,因此在处理冲突和存储元素时可能需要更复杂的逻辑。

在实际应用中,根据具体的需求和数据特性选择合适的数据结构是非常重要的。例如,在需要统计词频的场景中,由于一个单词可能在文本中出现多次,因此使用unordered_multiset来存储单词和它们的出现次数会更合适。而在某些需要唯一标识的场景中,如用户ID的存储,使用unordered_set来确保ID的唯一性则更为合适。

3. 实际应用案例分析

unordered系列数据结构在实际项目中有着广泛的应用,特别是在需要快速查找和插入的场景中。

案例一:词频统计

在处理大量文本数据时,词频统计是一个常见的任务。可以使用unordered_map来存储每个单词及其出现的次数。由于哈希表提供了平均常数时间的查找和插入操作,因此这种方法在处理大规模文本时非常高效。

案例二:缓存系统

在缓存系统中,通常需要快速查找和插入键值对。unordered_mapunordered_set可以用作缓存的底层数据结构,提供快速的访问速度。当缓存达到最大容量时,还可以使用这些数据结构来高效地执行替换策略(如LRU缓存替换)。

本文完整代码: unordered_map与unordered_set · 比奇堡的Zyb/每日学习 - 码云 - 开源中国 (gitee.com)

相关文章:

从哈希桶角度看 unordered_map 与 unordered_set 的实现

文章目录 一、引言二、C unordered系列的无序关联式容器概览三、基于哈希桶的C unordered系列数据结构模拟实现1、unordered_map的模拟实现2、unordered_set的模拟实现3、哈希桶及其迭代器实现的代码 四、扩展与应用1. 自定义哈希函数2. 其他unordered数据结构unordered_multim…...

飞天使-k8s知识点27-kubernetes温故知新2-deployment

文章目录 RC和RS无状态应用管理 deployment有状态应用statefulSetdaemonSet RC和RS RC不会使用在生产环境 RS 比RC 多了标签选择器 &#xff0c;RS 用deployment管理&#xff0c;用于容器编排无状态应用管理 deployment apiVersion: apps/v1 kind: Deployment metadata:name:…...

手机网页关键词视频爬虫采集软件可导出视频分享链接|视频无水印批量下载工具

全新音视频批量下载工具&#xff0c;为您解放视频管理烦恼&#xff01; 现如今&#xff0c;音上涌现出大量精彩的视频内容&#xff0c;但是要想高效地获取、管理和分享这些视频却是一件颇具挑战的事情。针对这一难题&#xff0c;我们自主研发了全新的音视频批量下载工具&#x…...

基于OpenCV的图像处理案例之图像矫正(Python)

Index 目录索引 写在前面解决思路参考 写在前面 本文通过一个案例介绍如何使用OpenCV将倾斜的扫描文档图像进行水平矫正。 解决思路 因为扫描图像中的大部分文字倾斜后&#xff0c;同一行文字也在同一条直线&#xff0c;所以可以通过拟合直线来计算文本倾斜角度&#xff0c;…...

创建linux虚拟机系统:(安装Ubuntu镜像文件,包含语言设置、中文输入法、时间设置)

我下载的是清华大写开源软件镜像站中的ubuntu-20.04.6-desktop-amd64.iso这个镜像文件&#xff0c; 这个文件我下载完成之后没有解压&#xff0c;直接在创建虚拟机的时候选择的压缩包。 地址为&#xff1a;Index of /ubuntu-releases/20.04/ | 清华大学开源软件镜像站 | Tsin…...

3.0 V-22V 宽输入电压,高效率异步升压芯片-ZCC5429

一、产品综述 ZCC5429 芯片是一款自动调频、最高 600KHz工作频率、高效率、宽输入电压范围的电流模式异 步升压&#xff08;BOOST&#xff09;芯片&#xff0c;且可调输入限流功能。用户可灵活地通过外部补偿建立动态环路&#xff0c;获得在所有条件下最优瞬态性能。 ZCC542…...

Sphinx + Readthedocs 避坑速通指南

博主在学习使用 Sphinx 和 Read the docs 的过程中&#xff0c; 碰到了许多奇葩的 bug, 使得很简单的任务花费了很长的时间才解决&#xff0c;现在在这里做一个分享&#xff0c;帮助大家用更少的时间高效上线文档的内容。 总的来说&#xff0c; 任务分为两个部分&#xff1a; …...

IPP-7010 表面贴装 90 度混合耦合器

IPP-7010 表面贴装 90 度混合耦合器 IPP-7010 是一款表面贴装 90 度混合耦合器&#xff0c;工作频率为 800 至 2500 MHz&#xff08;0.8 至 2.5 GHz&#xff09;&#xff0c;平均额定功率为 200 瓦。IPP-7010 采用 0.40 x 1.80 英寸表面贴装封装。IPP-7010的幅度平衡小于0.6dB&…...

25.2 微服务Dubbo

25.2 微服务Dubbo 1. Dubbo简介2. RPC3. Dubbo工作原理4. 代码实操4.1 父项目1. 依赖4.2 服务提供者1. 依赖2. 配置文件3. 启动类4. 业务类4.3 服务消费者1. 依赖2. 配置文件3. 消费者启动类4. 业务:实现远程调用...

CI/CD环境搭建

服务简介 Gitlab 官网&#xff1a;https://about.gitlab.com/ GitLab 是一个用于仓库管理系统的开源项目&#xff0c;使用Git作为代码管理工具&#xff0c;并在此基础上搭建起来的Web服务。安装方法是参考GitLab在GitHub上的Wiki页面。Gitlab是被广泛使用的基于git的开源代码管…...

API调试管理工具Postman下载及操作介绍

1.下载安装postman地址&#xff1a;https://www.getpostman.com/downloads/ 2.创建项目 3.创建请求API 然后点击save保存api 4.用一个变量保存主域名&#xff0c;方便后续操作 就类似下面的baseurl 5.创建新环境 6.添加变量&#xff08;如添加本地测试环境url——ba…...

vue集成百度地图,实现关键字搜索并自定义覆盖物,保存成静态图片

vue集成百度地图&#xff0c;实现关键字搜索并自定义覆盖物 index.html引入百度地图js <script type"text/javascript" src"https://api.map.baidu.com/api?v2.0&typewebgl&akxxxxxxwMprS7jIfPt354VdgP"></script>vue页面代码 <…...

Java中的Stream流

一、介绍 1. Stream流的作用 结合了Lambda表达式&#xff0c;简化集合、数组的操作。 2. Stream流的使用步骤 ①先得到一条Stream流&#xff0c;并把数据放上去&#xff1b; 获取方式方法名说明单列集合default Stream<E> stream()Collection中的默认方法双列集合无无…...

前端UI怎么防止用户反复提交?

方法1&#xff1a;禁用按钮 用户点击“xxx”按钮后&#xff0c;先禁用按钮&#xff0c;防止用户多次点击&#xff1b;待请求完成后&#xff0c;再解禁按钮。 方法2&#xff1a;防抖&#xff08;Debouncing&#xff09; 防抖是一种技术&#xff0c;它可以延迟执行函数&#xff0…...

OpenHarmony游戏应用程序-实现的一个手柄游戏

介绍 本篇Codelab是基于TS扩展的声明式开发范式编程语言&#xff0c;以及OpenHarmony的分布式能力实现的一个手柄游戏。 说明&#xff1a; 本示例涉及使用系统接口&#xff0c;需要手动替换Full SDK才能编译通过。 完成本篇Codelab需要两台开发板&#xff0c;一台开发板作为游…...

Redis+Lua脚本+SpringAOP实现接口限流

提到限流,常规情况,可以通过spring-cloud-starter-alibaba-sentinel 或者 resilience4j-ratelimiter 组件完成,但是如果不借助现有组件让我们自己开发一套限流工作应该如何应对呢? 本次我们通过Redis + Lua 脚本来实现一个限流组件。 首先创建项目:redis-limit <?xml…...

【wpf应用8】如何让WPF Grid控件根据屏幕尺寸自动调整

简介&#xff1a; 在Windows Presentation Foundation&#xff08;WPF&#xff09;中&#xff0c;Grid控件是一个强大的布局工具&#xff0c;它允许开发者创建复杂且响应迅速的用户界面。在不同的设备和屏幕尺寸上保持良好的布局一致性是一个挑战。本文将介绍如何让Grid控件根据…...

掌握ChatGPT:如何用AI撰写高质量论文

ChatGPT无限次数:点击直达 掌握ChatGPT&#xff1a;如何用AI撰写高质量论文 在当今信息爆炸的时代&#xff0c;人们不仅需要大量信息&#xff0c;还需要这些信息的整理与创新。人工智能技术正是我们在这个信息化时代最强大的助手之一。ChatGPT是一款基于大型神经网络的语言生成…...

平衡隐私与效率,Partisia Blockchain 解锁数字安全新时代

原文&#xff1a;https://cointelegraph.com/news/exploring-multiparty-computations-role-in-the-future-of-blockchain-privacy&#xff1b; https://medium.com/partisia-blockchain/unlocking-tomorrow-outlook-for-mpc-in-2024-and-beyond-cb170e3ec567 编译&#xff1…...

【JavaScript】NPM常用指令指南

河水清清弯又长 姑娘水边浣霓裳 清风卷过白云旁 飞鸟载来春花香 河水清清弯又长 姑娘水边浣霓裳 清风卷过白云旁 朝霞换夕阳 重逢是梦乡 春潮悠悠送波浪 石桥湾下小舟荡 此去经年谁如常 难得人间笑一场 春潮悠悠送波浪 石桥湾下小舟荡 此去经年谁如常 故人心头上 地久天又长 …...

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…...

相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解

【关注我&#xff0c;后续持续新增专题博文&#xff0c;谢谢&#xff01;&#xff01;&#xff01;】 上一篇我们讲了&#xff1a; 这一篇我们开始讲&#xff1a; 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下&#xff1a; 一、场景操作步骤 操作步…...

线程同步:确保多线程程序的安全与高效!

全文目录&#xff1a; 开篇语前序前言第一部分&#xff1a;线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分&#xff1a;synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分&#xff…...

uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖

在前面的练习中&#xff0c;每个页面需要使用ref&#xff0c;onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入&#xff0c;需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...

AtCoder 第409​场初级竞赛 A~E题解

A Conflict 【题目链接】 原题链接&#xff1a;A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串&#xff0c;只有在同时为 o 时输出 Yes 并结束程序&#xff0c;否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...

【第二十一章 SDIO接口(SDIO)】

第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...

ETLCloud可能遇到的问题有哪些?常见坑位解析

数据集成平台ETLCloud&#xff0c;主要用于支持数据的抽取&#xff08;Extract&#xff09;、转换&#xff08;Transform&#xff09;和加载&#xff08;Load&#xff09;过程。提供了一个简洁直观的界面&#xff0c;以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级

在互联网的快速发展中&#xff0c;高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司&#xff0c;近期做出了一个重大技术决策&#xff1a;弃用长期使用的 Nginx&#xff0c;转而采用其内部开发…...

Matlab | matlab常用命令总结

常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...

微信小程序云开发平台MySQL的连接方式

注&#xff1a;微信小程序云开发平台指的是腾讯云开发 先给结论&#xff1a;微信小程序云开发平台的MySQL&#xff0c;无法通过获取数据库连接信息的方式进行连接&#xff0c;连接只能通过云开发的SDK连接&#xff0c;具体要参考官方文档&#xff1a; 为什么&#xff1f; 因为…...