STL容器之unordered_map类

文章目录

  • STL容器之unordered_map类
    • 1、unordered_map
      • 1.1、unordered_map介绍
      • 1.2、unordered_map的使用
        • 1.2.1、unordered_map的常见构造
        • 1.2.2、unordered_map的迭代器
        • 1.2.3、unordered_map的容量
        • 1.2.4、unordered_map的增删查
        • 1.2.5、unordered_map的桶操作
    • 2、unordered_multimap
    • 3、unordered_map的底层结构
    • 4、unordered_set的模拟实现
      • 4.1、改造哈希表(链表法)
      • 4.2、MyUnordered_Map类的构成

img

STL容器之unordered_map类

1、unordered_map

1.1、unordered_map介绍

unordered_map的文档介绍

  1. unordered_map是以不特定顺序存储独特元素的容器,并允许根据其值快速检索单个元素。

  2. 在unordered_map中,键值通常用于唯一标识元素,而映射值是具有与此键关联内容的对象(pair<K,V>)。键是不可变的。键和映射值的类型可能不同。

  3. 在内部,unordered_map中的元素没有按任何特定顺序排序,而是根据其哈希值组织成桶,以便通过其值直接快速访问单个元素(平均时间复杂度恒定)。

  4. unordered_map容器比map容器更快地通过其键访问单个元素,但是它通常在遍历元素子集的范围迭代方面效率较低。

  5. unordered_map实现了直接访问运算符(运算符[]),它允许使用其键值作为参数直接访问映射值。

  6. 容器中的迭代器至少是前向iterators。


1.2、unordered_map的使用

1.2.1、unordered_map的常见构造
(constructor )函数名称接口说明
unordered_map ( size_type n = /* see below */, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& alloc = allocator_type() )构造空的unordered_map
unordered_map ( InputIterator first, InputIterator last, size_type n = /* see below */, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& alloc = allocator_type() )用[first,last)迭代区间构造unordered_map
unordered_map ( const unordered_map& ump )unordered_map的拷贝构造
void test_um1() {unordered_map<int, int> um;int a[]{1, 2, 5, 7, 2, 3, 5, 8, 2, 11, 9};for (auto e: a) {um.insert(make_pair(e, e));}for (auto e: um) {cout << e.first << ":" << e.second << endl;}cout << "=======================" << endl;unordered_map<int, int> um1(um.begin(), um.end());for (auto e: um1) {cout << e.first << ":" << e.second << endl;}cout << "=======================" << endl;unordered_map<int, int> um2(um1);for (auto e: um2) {cout << e.first << ":" << e.second << endl;}}

1.2.2、unordered_map的迭代器
函数名称接口说明
begin()+end()获取第一个元素位置的iterator和获取最后一个元素的后一个位置的iterator
cbegin()+cend()获取第一个元素位置的const_iterator和获取最后一个元素的后一个位置的const_iterator
void test_um2() {unordered_map<int, int> um;int a[]{1, 2, 5, 7, 2, 3, 5, 8, 2, 11, 9};for (auto e: a) {um.insert(make_pair(e, e));}unordered_map<int, int>::iterator it = um.begin();while (it != um.end()) {cout << it->first << ":" << it->second << endl;++it;}cout << "=======================" << endl;unordered_map<int, int>::const_iterator cit = um.cbegin();while (cit != um.cend()) {cout << cit->first << ":" << cit->second << endl;++cit;}}

1.2.3、unordered_map的容量
函数名称接口说明
empty判断当前unordered_map是否为空
size获取unordered_map的元素个数
void test_um3() {unordered_map<int, int> um;int a[]{1, 2, 5, 7, 2, 3, 5, 8, 2, 11, 9};for (auto e: a) {um.insert(make_pair(e, e));}cout << um.empty() << endl;cout << um.size() << endl;um.clear();cout << um.empty() << endl;cout << um.size() << endl;
}

1.2.4、unordered_map的增删查
函数名称接口说明
insert在unordered_map中插入pair<key,value>键值对,如果插入成功,返回<key插入位置,true>,插入失败说明unordered_map中已经有key,返回<key在unordered_map的位置,false>
erase删除unordered_map中pos位置的元素,或者删除值为val的元素
swap交换两个unordered_map的元素
clear将unordered_map的元素置空
find返回unordered_map中值为x的元素位置
count返回unordered_map中值为x的元素个数
operator[]访问key元素的映射值value,如果key不存在,则插入pair<key,V()>并返回V();如果key存在,则返回对应的value
void test_um4() {unordered_map<int, int> um;int a[]{1, 2, 5, 7, 2, 3, 5, 8, 2, 11, 9};for (auto e: a) {um.insert(make_pair(e, e));}for (auto e: um) {cout << e.first << ":" << e.second << endl;}cout << "========================" << endl;um.erase(1);um.erase(2);auto pos = um.find(11);um.erase(pos);for (auto e: um) {cout << e.first << ":" << e.second << endl;}cout << "========================" << endl;unordered_map<int, int> um1;um1.insert(make_pair(100, 100));um1.swap(um);cout << "um:";for (auto e: um) {cout << e.first << ":" << e.second << endl;}cout << "um1:";for (auto e: um1) {cout << e.first << ":" << e.second << endl;}cout << "========================" << endl;cout << um1.count(5) << endl;cout << um1.count(1) << endl;cout << "========================" << endl;um1.clear();cout << "um:";for (auto e: um) {cout << e.first << ":" << e.second << endl;}cout << "um1:";for (auto e: um1) {cout << e.first << ":" << e.second << endl;}}

1.2.5、unordered_map的桶操作
函数名称接口说明
bucket_count返回unordered_map中的桶的个数
bucket_size返回第n个桶中元素的个数
bucket返回元素k在哪个桶
void test_um5() {unordered_map<int, int> um;int a[]{1, 2, 5, 7, 2, 3, 5, 8, 2, 11, 9};for (auto e: a) {um.insert(make_pair(e, e));}cout << um.bucket_count() << endl;cout << um.bucket_size(1) << endl;cout << um.bucket(11) << endl;
}

2、unordered_multimap

这个其实就和map和multimap一样,就是比unordered_map多了一个可以存重复值的特性。

演示一下:

void test_umm1() {unordered_multimap<int, int> ummp;int a[]{1, 2, 5, 7, 2, 3, 5, 8, 2, 11, 9};for (auto e: a) {ummp.insert(make_pair(e, e));}for (auto e: ummp) {cout << e.first << ":" << e.second << endl;}cout << endl;
}

3、unordered_map的底层结构

unordered系列的关联式容器之所以效率比较高,是因为其底层使用了哈希结构。

unordered_map和unordered_set一样,底层都是用的哈希表,都是用的链表法。

想了解底层结构可以看STL容器之unordered_set类这篇文章


4、unordered_set的模拟实现

以下我们自己模拟实现的时候,unordered_set的模拟实现我们使用MyUnordered_Set类用于区分,unordered_map的模拟实现我们使用MyUnordered_Map类用于区分

4.1、改造哈希表(链表法)

结点的结构体需要修改一下,之前我们存的是pair<K,V>,但MyUnordered_Set是存K的,因此我们模版参数设置为一个参数T,MyUnordered_Set调用就是K,MyUnordered_Map调用就是pair<K,V>

template<class T>
struct HashNode {typedef HashNode<T> Node;Node *_next;T _data;HashNode(const T &data) : _data(data), _next(nullptr) {}};

哈希表需要增加一个模版参数:取Key的仿函数,因为MyUnordered_Set插入的是K,但是MyUnordered_Map插入的是pair<K,V>,我们需要从pair<K,V>中取出K。因此插入也要改成bool Insert(const T &data){}

这个仿函数分别放在MyUnordered_SetMyUnordered_Map的类中,用来传给哈希表。

MyUnordered_Set类中:

struct MapKeyOfT {K operator()(const pair<K, V> &kv) {return kv.first;}
};

MyUnordered_Map类中:

struct MapKeyOfT {K operator()(const pair<K, V> &kv) {return kv.first;}
};

因此当前改造后的哈希表为:

template<class T>
struct HashNode {typedef HashNode<T> Node;Node *_next;T _data;HashNode(const T &data) : _data(data), _next(nullptr) {}};template<class K>
struct HashFunc {size_t operator()(const K &key) {return (size_t) key;}
};template<>
struct HashFunc<string> {size_t operator()(const string &str) {size_t hash = 0;for (auto e: str) {hash += e;e *= 131;}return hash;}
};template<class K, class T, class KeyOfT, class Hash>
class HashTable {typedef HashNode<T> Node;
public:~HashTable() {for (int i = 0; i < _tables.size(); ++i) {_tables[i] = nullptr;}}HashTable(size_t size = 10) {_tables.resize(size, nullptr);// 各结点初始化为空}Node* Find(const K &key) {Hash hs;KeyOfT kot;// 先算出映射到哪里int hashi = hs(key) % _tables.size();Node *cur = _tables[hashi];while (cur) {if (kot(cur->_data) == key) {return cur;}cur = cur->_next;}return nullptr; // 没找到}bool Erase(const K &key) {Hash hs;KeyOfT kot;iterator ret = Find(key);if (ret != end()) {int hashi = hs(key) % _tables.size();Node *cur = _tables[hashi];Node *prev = nullptr;while (cur) {if (kot(cur->_data) == key) {if (prev == nullptr)_tables[hashi] = cur->_next; // 要删除的就是表中的结点,那么将它的下一个结点放到表中elseprev->_next = cur->_next; // 要删除的是表中的结点的后继中的某个delete cur; // 删除该结点并退出循环break;}prev = cur;cur = cur->_next;}--_n;return true;} else {return false;}}bool Insert(const T &data) {Hash hs;KeyOfT kot;if (Find(kot(data)))return false;// 找到了if (_n == _tables.size()) {// 扩容vector<Node *> newTables;newTables.resize(2 * _tables.size(), nullptr);for (int i = 0; i < _tables.size(); ++i) {Node *cur = _tables[i];while (cur) {Node *next = cur->_next; //记录下一个结点位置,防止找不到下一个结点// 映射到新表位置int hashi = hs(kot(cur->_data)) % newTables.size();// 插入到新表位置Node *newcur = newTables[hashi];if (newcur) {// 当前表中的结点不为空,则头插并链接cur->_next = newcur;newTables[hashi] = cur;} else {// 当前表中的结点为空,则新结点直接放到这个表中newTables[hashi] = cur;cur->_next = nullptr;// 新插入的cur的_next不一定是空}cur = next;// 继续往下找}}_tables.swap(newTables);}// 先算出映射到哪里int hashi = hs(kot(data)) % _tables.size();Node *cur = _tables[hashi];Node *newnode = new Node(data);if (cur) {// 当前表中的结点不为空,则头插并链接newnode->_next = cur;_tables[hashi] = newnode;} else {// 当前表中的结点为空,则新结点直接放到这个表中_tables[hashi] = newnode;}++_n;return true;}private:vector<Node *> _tables;size_t _n = 0;
};

还需要增加迭代器,用来遍历哈希表。

// 前置声明
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;}Self &operator++() {if (_node->_next) {// 当前结点还有后继结点_node = _node->_next;} else {// 当前桶走完了KeyOfT kot;Hash hs;// 先算出当前在哪个哈希桶int hashi = hs(kot(_node->_data)) % _ht->_tables.size();++hashi;// 走到下一个桶while (hashi < _ht->_tables.size()) {if (_ht->_tables[hashi]) {//  这个桶有结点_node = _ht->_tables[hashi];break;} else++hashi;// 这个桶没有有结点}if (hashi == _ht->_tables.size()) {// 走到最后了,没找到下一个位置_node = nullptr;}}return *this;}bool operator!=(const Self &s) {return s._node != _node;}
};

改造后的哈希表(终极版):这里的插入的返回值由bool变为了pair<iterator,bool>,和官方保持一致。

template<class T>
struct HashNode {typedef HashNode<T> Node;Node *_next;T _data;HashNode(const T &data) : _data(data), _next(nullptr) {}};template<class K>
struct HashFunc {size_t operator()(const K &key) {return (size_t) key;}
};template<>
struct HashFunc<string> {size_t operator()(const string &str) {size_t hash = 0;for (auto e: str) {hash += e;e *= 131;}return hash;}
};// 前置声明
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;}Self &operator++() {if (_node->_next) {// 当前结点还有后继结点_node = _node->_next;} else {// 当前桶走完了KeyOfT kot;Hash hs;// 先算出当前在哪个哈希桶int hashi = hs(kot(_node->_data)) % _ht->_tables.size();++hashi;// 走到下一个桶while (hashi < _ht->_tables.size()) {if (_ht->_tables[hashi]) {//  这个桶有结点_node = _ht->_tables[hashi];break;} else++hashi;// 这个桶没有有结点}if (hashi == _ht->_tables.size()) {// 走到最后了,没找到下一个位置_node = nullptr;}}return *this;}bool operator!=(const Self &s) {return s._node != _node;}
};template<class K, class T, class KeyOfT, class Hash>
class HashTable {friend __HTIterator<K, T, KeyOfT, Hash>;// 为了能访问_tablestypedef HashNode<T> Node;
public:typedef __HTIterator<K, T, KeyOfT, Hash> iterator;iterator begin() {for (int i = 0; i < _tables.size(); ++i) {if (_tables[i])return iterator(_tables[i], this);// 从左找到第一个哈希桶的第一个结点}return end();}iterator end() {return iterator(nullptr, this);}~HashTable() {for (int i = 0; i < _tables.size(); ++i) {_tables[i] = nullptr;}}HashTable(size_t size = 10) {_tables.resize(size, nullptr);// 各结点初始化为空}iterator Find(const K &key) {Hash hs;KeyOfT kot;// 先算出映射到哪里int 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); // 没找到}bool Erase(const K &key) {Hash hs;KeyOfT kot;iterator ret = Find(key);if (ret != end()) {int hashi = hs(key) % _tables.size();Node *cur = _tables[hashi];Node *prev = nullptr;while (cur) {if (kot(cur->_data) == key) {if (prev == nullptr)_tables[hashi] = cur->_next; // 要删除的就是表中的结点,那么将它的下一个结点放到表中elseprev->_next = cur->_next; // 要删除的是表中的结点的后继中的某个delete cur; // 删除该结点并退出循环break;}prev = cur;cur = cur->_next;}--_n;return true;} else {return false;}}pair<iterator, bool> Insert(const T &data) {Hash hs;KeyOfT kot;iterator it = Find(kot(data));if (it != end())return make_pair(it, false);// 找到了if (_n == _tables.size()) {// 扩容vector<Node *> newTables;newTables.resize(2 * _tables.size(), nullptr);for (int i = 0; i < _tables.size(); ++i) {Node *cur = _tables[i];while (cur) {Node *next = cur->_next; //记录下一个结点位置,防止找不到下一个结点// 映射到新表位置int hashi = hs(kot(cur->_data)) % newTables.size();// 插入到新表位置Node *newcur = newTables[hashi];if (newcur) {// 当前表中的结点不为空,则头插并链接cur->_next = newcur;newTables[hashi] = cur;} else {// 当前表中的结点为空,则新结点直接放到这个表中newTables[hashi] = cur;cur->_next = nullptr;// 新插入的cur的_next不一定是空}cur = next;// 继续往下找}}_tables.swap(newTables);}// 先算出映射到哪里int hashi = hs(kot(data)) % _tables.size();Node *cur = _tables[hashi];Node *newnode = new Node(data);if (cur) {// 当前表中的结点不为空,则头插并链接newnode->_next = cur;_tables[hashi] = newnode;} else {// 当前表中的结点为空,则新结点直接放到这个表中_tables[hashi] = newnode;}++_n;return make_pair(iterator(_tables[hashi], this), true);}private:vector<Node *> _tables;size_t _n = 0;
};

4.2、MyUnordered_Map类的构成

其实就是套了一层哈希表,多了一个MapKeyOfT用来传给哈希表的模版参数。

#include "HashTable_Bucket.h"template<class K, class V, class Hash = HashFunc<K>>
class MyUnordered_Map {struct MapKeyOfT {K operator()(const pair<K, V> &kv) {return kv.first;}};public:typedef typename HashTable<K, pair<const K, V>, MapKeyOfT, Hash>::iterator iterator;iterator begin() {return _hs.begin();}iterator end() {return _hs.end();}pair<iterator, bool> insert(const pair<K, V> &kv) {return _hs.Insert(kv);}bool erase(const K &key) {return _hs.Erase(key);}iterator find(const K &key) {return _hs.Find(key);}V &operator[](const K &key) {pair<iterator, bool> ret = insert(make_pair(key, V()));return ret.first->second;}private:HashTable<K, pair<const K, V>, MapKeyOfT, Hash> _hs;
};

OKOK,C++ STL容器之unordered_map类就到这里。如果你对Linux和C++也感兴趣的话,可以看看我的主页哦。下面是我的github主页,里面记录了我的学习代码和leetcode的一些题的题解,有兴趣的可以看看。

Xpccccc的github主页

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

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

相关文章

【快速上手ESP32(基于ESP-IDFVSCode)】04-PWM

PWM PWM&#xff0c;即脉冲宽度调制&#xff08;Pulse Width Modulation&#xff09;&#xff0c;是一种模拟控制方式&#xff0c;根据相应载荷的变化来调制晶体管基极或MOS管栅极的偏置&#xff0c;来实现晶体管或MOS管导通时间的改变&#xff0c;从而达到控制开关稳压电源输出…

物联网系统设计 8

1 规划中小型LoRa 中小型分时复用&#xff0c;大型项目需要学习LoRaWAN 1.1 通信记录 1.2 节点能耗 1278芯片 满功率20DMB&#xff0c;增加PA&#xff0c;发送功率 30 DBM 内置天线柔性 棒状 3db 203 休眠、发生、接收 计算链路预算&#xff0c;工作电流&#xff0c;工…

Blocs v5.2.3 mac版 可视化网页设计工具 兼容 M1/M2/M3

Mac毒搜集到的Blocs 是一款mac上专业强大的精美网页设计软件。特点就是简介、高效、高质&#xff0c;可以帮助我们快速设计出精美的网页&#xff0c;retina视网膜特性支持&#xff0c;优化自适应网页的开发。 应用介绍 Blocs 是一款mac上专业强大的精美网页设计软件。专注于简…

实现WAF对CC攻击的零误封防护:关键技术解析与实践

一、引言 Web应用防火墙&#xff08;WAF&#xff09;作为网站安全的重要防线&#xff0c;其在防御CC&#xff08;Challenge Collapsar&#xff0c;即挑战黑洞&#xff0c;一种分布式拒绝服务攻击&#xff09;攻击中的效能至关重要。然而&#xff0c;精准识别并有效拦截CC攻击的…

2024阿里云2核4G服务器优惠价格表_2核4G性能测评

阿里云2核4G服务器多少钱一年&#xff1f;2核4G服务器1个月费用多少&#xff1f;2核4G服务器30元3个月、85元一年&#xff0c;轻量应用服务器2核4G4M带宽165元一年&#xff0c;企业用户2核4G5M带宽199元一年。本文阿里云服务器网整理的2核4G参加活动的主机是ECS经济型e实例和u1…

pytesseract,一个超强的 Python 库!

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com 大家好&#xff0c;今天为大家分享一个超强的 Python 库 - pytesseract。 Github地址&#xff1a;https://github.com/madmaze/pytesseract 在当今数字化时代&#xff0c;文字识别技术扮演着越来越重要的角色。…

设计模式-装饰者模式(Decorator)

1. 概念 装饰者模式是一种结构型设计模式&#xff0c;它允许用户在不修改原始对象的基础上&#xff0c;通过将对象包装在装饰者类的对象中&#xff0c;动态地给原始对象添加新的行为或职责。 2. 原理结构图 图1 图2 抽象组件&#xff08;Component&#xff09;&#xff1a…

离散化实现低通滤波器(选用双线性变换)

学习了离散化后整理了其中的核心步骤&#xff0c;此处不对原理进行深究&#xff0c;仅仅介绍如何对一个连续系统进行离散化 此处可以得到低通滤波器的截止频率为1000rad/s. 离散化的过程为将s 2/Ts * [(z - 1) / (z 1)] (选用双线性变换) 得到离散化序列为 Y(z) [w…

Python-VBA函数之旅-bytearray函数

目录 1、bytearray函数&#xff1a; 1-1、Python&#xff1a; 1-2、VBA&#xff1a; 2、相关文章&#xff1a; 个人主页&#xff1a;非风V非雨-CSDN博客 bytearray函数在Python中提供了一种可变字节序列的表示方式&#xff0c;这在实际编程中有多种应用场景。常见的应用场…

如何用Python编写简单的网络爬虫(页面代码简单分析过程)

一、什么是网络爬虫 在当今信息爆炸的时代&#xff0c;网络上蕴藏着大量宝贵的信息&#xff0c;如何高效地从中获取所需信息成为了一个重要课题。网络爬虫&#xff08;Web crawler&#xff09;作为一种自动化工具&#xff0c;可以帮助我们实现这一目标&#xff0c;用于数据分析…

项目实战 | 使用python分析Excel销售数据(用groupby)

项目实战 | 使用python分析Excel销售数据 本文目录&#xff1a; 零、00时光宝盒 一、提出问题 二、理解数据 2.1、安装python读取excel文件的库 2.2、查看excel表的字段名和前几行记录 2.3、查看excel表结构 2.4、查看索引 2.5、查看每一列的列表头内容 2.6、查看每一…

移除元素Java实现

题意 给你一个数组 nums 和一个值 val&#xff0c;你需要 原地 移除所有数值等于 val 的元素&#xff0c;并返回移除后数组的新长度。 不要使用额外的数组空间&#xff0c;你必须仅使用 额外空间 并 原地 修改数组。 元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元…

websocket实践

文章目录 背景WebSocket API使用场景优点 实例步骤 1: 设置 WebSocket 服务器步骤 2: 创建客户端 HTML 页面步骤 3: 测试 WebSocket 通信注意事项实际操作 参考资料 WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议。它使得浏览器和服务器只需建立一个连接&#xff0c;…

CSS:filter属性介绍

一、filter属性简介 值描述示例blur(Npx)设置高斯模糊效果。N是模糊半径&#xff0c;值越大&#xff0c;模糊效果越明显。filter: blur(5px);brightness(%)调整图像的亮度。百分比值小于100%会使图像变暗&#xff0c;大于100%会使图像变亮。filter: brightness(75%);contrast(…

el-table合计行添加按钮操作

针对于el-table中合计功能中的操作栏也可以按钮&#xff0c;并且可以添加点击事件 ElTable源码里footer部分是&#xff0c;这种方式渲染的&#xff0c;也就是 支持传递VNode。使用h第一个参数传递 组件&#xff0c;可以把组件转成VNode&#xff0c;比如现在要在右下角加一个 详…

无货源,0基础做电商,6个选品逻辑快速出单!

首先我们要先解决货源问题&#xff0c;再来谈选品逻辑。初入电商行业&#xff0c;进货渠道建议使用1688。首先1688是国内最大的B2B批发平台&#xff0c;平台服务和安全性都提供了一定的保障&#xff0c;以及丰富的货源选择。你可以浏览不同供应商的产品&#xff0c;对比价格、质…

如何关闭WordPress的自动更新功能

Wordpress为什么自动更新 WordPress自动更新是为了提供更好的安全性和稳定性。 安全性&#xff1a;WordPress是一个广泛使用的内容管理系统&#xff0c;因此成为恶意攻击的目标。WordPress的自动更新功能确保你的网站及时获得最新的安全补丁和修复程序&#xff0c;以保护你的网…

【智能优化算法】基于领导者优化的哈里斯鹰优化算法(LHHO)

01.引言 基于领导者优化的哈里斯鹰优化算法leader Harris hawks optimization (LHHO)&#xff0c;以增强Harris hawks optimization (HHO)的搜索能力。通过在探索阶段的适应性栖息和每一代哈里斯鹰的基于领导者的突变选择&#xff0c;可以实现更多的探索。使用经典的23个基准函…

Flink常见面试问题(附答案)

目录 基础篇1. 什么是Apache Flink&#xff1f;2. Flink与Hadoop的区别是什么&#xff1f;3. Flink中的事件时间&#xff08;Event Time&#xff09;和处理时间&#xff08;Processing Time&#xff09;有什么区别&#xff1f;4. Flink的容错机制是如何实现的&#xff1f;5. 什…

node.js 包管理工具介绍 (npm与Yarn详细说明)

一、什么是包&#xff1f; 包&#xff08;package&#xff09;代表了一组特定功能的源码集合 二、什么是包管理工具&#xff1f; 也就是管理包的应用软件&#xff0c;可以对包进行下载、更新、删除、上传等操作。借助包管理工具&#xff0c;可以快速开发项目提升开发效率。包…