️博主简介:
文章目录
- 前言
- 一、源码即框架分析
- 二、模拟实现 unordered_map 和 unordered_set
- 2.1、实现出复用哈希表的框架,并支持 insert
- 2.2、支持 iterator 的实现
- (1)iterator 实现思路分析
- 2.3、unordered_map 支持 [ ]
- 三、unordered_map 和 unordered_set 代码实现
- 总结
前言
我们在上一章节了解完我们的哈希表是怎么实现后,我们又有 map/set 封装的经验,那我们的 unordered_map/unordered_set 的封装就会显得相对简单了,和我们 map/set 是差不多的,主要难点可能也是在迭代器的实现上了,我们就一起来看看吧。
一、源码即框架分析
我们 unordered_map/unordered_set 的实现和 map/set 实现的结构其实是一样的,我们都是用一个结构复用同时实现的, map/set 复用的是红黑树,而 unordered_map/unordered_set 复用的则是哈希表了。
通过源码可以看到,结构上 hash_map 和 hash_set 跟 map 和 set 的完全类似,复用同一个 hashtable 实现 key 和 key/value 结构,hash_set 传给 hash_table 的是两个 key,hash_map 传给 hash_table 的是 pair<const key, value>注意:
源码里面跟 map/set 源码类似,命名风格比较乱,这里比 map 和 set 还乱,hash_set 模板参数居然用的 Value 命名,hash_map 用的是 Key 和 T 命名,可见⼤佬有时写代码也不规范。下面我们模拟一份自己的出来,就按自己的风格⾛了。
二、模拟实现 unordered_map 和 unordered_set
2.1、实现出复用哈希表的框架,并支持 insert
和 map/set 的思路是一样的,创建一个模板,我们想要让哈希表是什么 key 还是 key/value,就传什么类型的即可。
// MyUnorderedSet.h
template<
class K
>
class unordered_set
{
struct SetKeyOfT
{
const K&
operator()(const K& key)
{
return key;
}
};
public:
bool insert(const K& key)
{
return _ht.Insert(key);
}
private:
hash_bucket::HashTable<K, K, SetKeyOfT> _ht;};
// MyUnorderedMap.h
template<
class K
, class V
>
class unordered_map
{
struct MapKeyOfT
{
const K&
operator()(const pair<K, V>& kv){return kv.first;}};public:bool insert(const pair<K, V>& kv){return _ht.Insert(kv);}private:hash_bucket::HashTable<K, pair<K, V>, MapKeyOfT> _ht;};
// HashTable.h
template<
class K
>
struct HashFunc
{
size_t operator()(const K& key)
{
return (size_t)key;
}
};
namespace hash_bucket
{
template<
class T
>
struct HashNode
{
T _data;
HashNode<T>* _next;HashNode(const T& data):_data(data), _next(nullptr){}};// 实现步骤:// 1、实现哈希表// 2、封装unordered_map和unordered_set的框架 解决KeyOfT// 3、iterator// 4、const_iterator// 5、key不⽀持修改的问题// 6、operator[]template<class K, class T, class KeyOfT>class HashTable{typedef HashNode<T> Node;inline unsigned long __stl_next_prime(unsigned long n){static const int __stl_num_primes = 28;static const unsigned long __stl_prime_list[__stl_num_primes] ={53, 97, 193, 389, 769,1543, 3079, 6151, 12289, 24593,49157, 98317, 196613, 393241, 786433,1572869, 3145739, 6291469, 12582917, 25165843,50331653, 100663319, 201326611, 402653189, 805306457,1610612741, 3221225473, 4294967291};const unsigned long* first = __stl_prime_list;const unsigned long* last = __stl_prime_list + __stl_num_primes;const unsigned long* pos = lower_bound(first, last, n);return pos == last ? *(last - 1) : *pos;}public:HashTable(){_tables.resize(__stl_next_prime(_tables.size()), nullptr);}~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;}}bool Insert(const T& data){KeyOfT kot;if (Find(kot(data)))return false;size_t hashi = kot(data) % _tables.size();// 负载因⼦==1扩容if (_n == _tables.size()){vector<Node*>newtables(__stl_next_prime(_tables.size()), nullptr);for (size_t i = 0; i < _tables.size(); i++){Node* cur = _tables[i];while (cur){Node* next = cur->_next;// 旧表中结点,挪动新表重新映射的位置size_t hashi = kot(cur->_data) % newtables.size();// 头插到新表cur->_next = newtables[hashi];newtables[hashi] = cur;cur = next;}_tables[i] = nullptr;}_tables.swap(newtables);}// 头插Node* newnode = new Node(data);newnode->_next = _tables[hashi];_tables[hashi] = newnode;++_n;return true;}private:vector<Node*> _tables;// 指针数组size_t _n = 0;// 表中存储数据个数};}
2.2、支持 iterator 的实现
(1)iterator 实现思路分析
iterator 实现的大框架:
跟 list 的 iterator 思路是一致的,用一个类型封装结点的指针,再通过重载运算符实现,迭代器像指针一样访问的行为,要注意的是哈希表的迭代器是单向迭代器。
template<
class K
, class T
, class Ptr
, class Ref
, class KeyOfT
, class Hash
>
struct HTIterator
{
typedef HashNode<T> Node;typedef HTIterator<K, T, Ptr, Ref, KeyOfT, Hash> Self;Node* _node;const HashTable<K, T, KeyOfT, Hash>* _pht;HTIterator(Node* node, const HashTable<K, T, KeyOfT, Hash>* pht):_node(node), _pht(pht){}Ref operator*(){}Ptr operator->(){}bool operator!=(const Self& s){}Self&operator++(){}};
iterator 实现思路分析:
- 这里的难点是 operator++ 的实现。iterator 中有一个指向结点的指针,如果当前桶下面还有结点,则结点的指针指向下一个结点即可。如果当前桶走完了,则需要想办法计算找到下一个桶。这里的难点反而是结构设计的问题,参考上面的源码,我们可以看到 iterator 中除了有结点的指针,还有哈希表对象的指针,这样当前桶走完了,要计算下一个桶就相对容易多了,用 key 值计算出当前桶位置,依次往后找下一个不为空的桶即可。
Self&
operator++()
{
if (_node->_next)
{
// 当前桶还有节点
_node = _node->_next;
}
else
{
// 当前桶⾛完了,找下⼀个不为空的桶
KeyOfT kot;
Hash hs;
size_t hashi = hs(kot(_node->_data)) % _pht -> _tables.size();
++hashi;
while (hashi < _pht->_tables.size()){if (_pht->_tables[hashi]){break;}++hashi;}if (hashi == _pht->_tables.size()){_node = nullptr;// end()}else{_node = _pht->_tables[hashi];}}return *this;}
- begin() 返回第一个桶中第一个节点指针构造的迭代器,这里 end() 返回迭代器可以用空表示。
typedef HTIterator<K, T, T*, T&
, KeyOfT, Hash> Iterator;
typedef HTIterator<K, T, const T*, const T&
, KeyOfT, Hash> ConstIterator;
Iterator Begin()
{
if (_n == 0)
return End();
for (size_t i = 0; i < _tables.size(); i++)
{
Node* cur = _tables[i];
if (cur)
{
return Iterator(cur, this);
}
}
return End();
}
Iterator End()
{
return Iterator(nullptr, this);
}
ConstIterator Begin() const
{
if (_n == 0)
return End();
for (size_t i = 0; i < _tables.size(); i++)
{
Node* cur = _tables[i];
if (cur)
{
return ConstIterator(cur, this);
}
}
return End();
}
ConstIterator End() const
{
return ConstIterator(nullptr, this);
}
- unordered_set 的 iterator 也不支持修改,我们把 unordered_set 的第二个模板参数改成 const K 即可,
HashTable<K, const K, SetKeyOfT, Hash> _ht - unordered_map 的 iterator 不支持修改 key 但是可以修改 value,我们把 unordered_map 的第二个模板参数 pair 的第一个参数改成 const K 即可, HashTable<K, pair<const K, V>, MapKeyOfT, Hash> _ht
// MyUnorderedSet.h
typedef typename hash_bucket::HashTable<K, const K, SetKeyOfT, Hash>::Iterator iterator;typedef typename hash_bucket::HashTable<K, const K, SetKeyOfT, Hash>::ConstIterator const_iterator;iterator begin(){return _ht.Begin();}iterator end(){return _ht.End();}const_iterator begin() const{return _ht.Begin();}const_iterator end() const{return _ht.End();}// MyUnorderedMap.htypedef typename hash_bucket::HashTable<K, pair<const K, V>, MapKeyOfT, Hash>::Iterator iterator;typedef typename hash_bucket::HashTable<K, pair<const K, V>, MapKeyOfT, Hash>::ConstIterator const_iterator;iterator begin(){return _ht.Begin();}iterator end(){return _ht.End();}const_iterator begin() const{return _ht.Begin();}const_iterator end() const{return _ht.End();}
实现了以上的代码,其余的就非常简单啦。
Ref operator*()
{
return _node->_data;
}
Ptr operator->
()
{
return &_node->_data;
}
bool operator!=(const Self& s)
{
return _node != s._node;
}
2.3、unordered_map 支持 [ ]
- unordered_map 要支持 [ ] 主要需要修改 insert 返回值支持,修改 HashTable 中的 insert 返回值为 pair<Iterator, bool> Insert(const T& data)
- 有了insert⽀持[]实现就很简单了
V&
operator[](const K& key)
{
pair<iterator, bool> ret = _ht.Insert(make_pair(key, V()));return ret.first->second;}
三、unordered_map 和 unordered_set 代码实现
// MyUnorderedSet.h
namespace bit
{
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;typedef typename hash_bucket::HashTable<K, const K, SetKeyOfT, Hash>::ConstIterator const_iterator;iterator begin(){return _ht.Begin();}iterator end(){return _ht.End();}const_iterator begin() const{return _ht.Begin();}const_iterator end() const{return _ht.End();}pair<iterator, bool>insert(const K & key){return _ht.Insert(key);}iterator Find(const K & key){return _ht.Find(key);}bool Erase(const K & key){return _ht.Erase(key);}private:hash_bucket::HashTable<K, const K, SetKeyOfT, Hash> _ht;};}// MyUnorderedMap.hnamespace bit{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;typedef typename hash_bucket::HashTable<K, pair<const K, V>, MapKeyOfT, Hash>::ConstIterator const_iterator;iterator begin(){return _ht.Begin();}iterator end(){return _ht.End();}const_iterator begin() const{return _ht.Begin();}const_iterator end() const{return _ht.End();}pair<iterator, bool>insert(const pair<K, V>& kv){return _ht.Insert(kv);}V&operator[](const K& key){pair<iterator, bool> ret = _ht.Insert(make_pair(key, V()));return ret.first->second;}iterator Find(const K& key){return _ht.Find(key);}bool Erase(const K& key){return _ht.Erase(key);}private:hash_bucket::HashTable<K, pair<const K, V>, MapKeyOfT, Hash> _ht;};}// HashTable.htemplate<class K>struct HashFunc{size_t operator()(const K& key){return (size_t)key;}};// 特化template<>struct HashFunc<string>{size_t operator()(const string& key){size_t hash = 0;for (auto e : key){hash *= 131;hash += e;}return hash;}};namespace hash_bucket{template<class T>struct HashNode{T _data;HashNode<T>* _next;HashNode(const T& data):_data(data), _next(nullptr){}};// 前置声明template<class K, class T, class KeyOfT, class Hash>class HashTable;template<class K, class T, class Ptr, class Ref, class KeyOfT, class Hash>struct HTIterator{typedef HashNode<T> Node;typedef HTIterator<K, T, Ptr, Ref, KeyOfT, Hash> Self;Node* _node;const HashTable<K, T, KeyOfT, Hash>* _pht;HTIterator(Node* node, const HashTable<K, T, KeyOfT, Hash>* pht):_node(node), _pht(pht){}Ref operator*(){return _node->_data;}Ptr operator->(){return &_node->_data;}bool operator!=(const Self& s){return _node != s._node;}Self&operator++(){if (_node->_next){// 当前桶还有节点_node = _node->_next;}else{// 当前桶⾛完了,找下⼀个不为空的桶KeyOfT kot;Hash hs;size_t hashi = hs(kot(_node->_data)) % _pht -> _tables.size();++hashi;while (hashi < _pht->_tables.size()){if (_pht->_tables[hashi]){break;}++hashi;}if (hashi == _pht->_tables.size()){_node = nullptr;// end()}else{_node = _pht->_tables[hashi];}}return *this;}};template<class K, class T, class KeyOfT, class Hash>class HashTable{// 友元声明template<class K, class T, class Ptr, class Ref, class KeyOfT, class Hash>friend struct HTIterator;typedef HashNode<T> Node;public:typedef HTIterator<K, T, T*, T&, KeyOfT, Hash> Iterator;typedef HTIterator<K, T, const T*, const T&, KeyOfT, Hash> ConstIterator;Iterator Begin(){if (_n == 0)return End();for (size_t i = 0; i < _tables.size(); i++){Node* cur = _tables[i];if (cur){return Iterator(cur, this);}}return End();}Iterator End(){return Iterator(nullptr, this);}ConstIterator Begin() const{if (_n == 0)return End();for (size_t i = 0; i < _tables.size(); i++){Node* cur = _tables[i];if (cur){return ConstIterator(cur, this);}}return End();}ConstIterator End() const{return ConstIterator(nullptr, this);}inline unsigned long __stl_next_prime(unsigned long n){static const int __stl_num_primes = 28;static const unsigned long __stl_prime_list[__stl_num_primes] ={53, 97, 193, 389, 769,1543, 3079, 6151, 12289, 24593,49157, 98317, 196613, 393241, 786433,1572869, 3145739, 6291469, 12582917, 25165843,50331653, 100663319, 201326611, 402653189, 805306457,1610612741, 3221225473, 4294967291};const unsigned long* first = __stl_prime_list;const unsigned long* last = __stl_prime_list + __stl_num_primes;const unsigned long* pos = lower_bound(first, last, n);return pos == last ? *(last - 1) : *pos;}HashTable(){_tables.resize(__stl_next_prime(_tables.size()), nullptr);}~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){KeyOfT kot;Iterator it = Find(kot(data));if (it != End())return make_pair(it, false);Hash hs;size_t hashi = hs(kot(data)) % _tables.size();// 负载因⼦==1扩容if (_n == _tables.size()){vector<Node*>newtables(__stl_next_prime(_tables.size() + 1), 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);}// 头插Node* newnode = new Node(data);newnode->_next = _tables[hashi];_tables[hashi] = newnode;++_n;return make_pair(Iterator(newnode, this), true);}Iterator Find(const K& key){KeyOfT kot;Hash hs;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 End();}bool Erase(const K& key){KeyOfT kot;Hash hs;size_t hashi = hs(key) % _tables.size();Node* prev = nullptr;Node* cur = _tables[hashi];while (cur){if (kot(cur->_data) == key){if (prev == nullptr){_tables[hashi] = cur->_next;}else{prev->_next = cur->_next;}delete cur;--_n;return true;}prev = cur;cur = cur->_next;}return false;}private:vector<Node*> _tables;// 指针数组size_t _n = 0;// 表中存储数据个数};}
总结
到此为止,我们以及学会了 C++ 的大部分的容器了,只剩下一些像位图等不算特别困难的容器我们到后面有机会再来细谈,下一章节开始我们就会来聊聊我们 C++ 的一次重大的更新,C++11 的一些非常使用的新特性,我们下一章节再见吧。
坚持到这里已经很厉害啦,辛苦啦 ʕ • ᴥ • ʔ づ♡ど
相关文章:
【STL库】哈希封装 unordered_map/unordered_set - 教程
【STL库】哈希封装 unordered_map/unordered_set - 教程pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", mon…...
用 Go 语言与 Tesseract OCR 识别英文数字验证码
一、安装与配置 安装 Tesseract OCR 你需要先安装 Tesseract OCR 引擎。具体步骤如下: Ubuntu: 更多内容访问ttocr.com或联系1436423940 sudo apt-get update sudo apt-get install tesseract-ocr macOS: brew install tesseract Windows: 可以从 Tesseract GitHub 下载并安装…...
FreeRTOS和LVGL组合使用教程
前言 关于这两者组合使用的教程,网上可以说是各种方法都有,移植的时候我也有遇到各种问题,在此处记录一下解决过程 问题 栈空间的分配问题 FreeRTOS和LVGL的栈分配都尽量多一点,不然后面的任务可能创建失败 lvgl心跳的问题 网上也有很多方法FreeRTOS钩子函数 单开一个定时器…...
Pip换源
清华大学源 比较全,但是没有torch pip config set global.index-url https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple南京大学源 有torch但是很多包没有,建议用来安装torch pip3 install torch torchvision torchaudio --index-url https://mirrors.nju.edu.cn/pytorch…...
7zip压缩解压缩-测试CPU性能
前言全局说明在B站刷大佬视频的时候,看到UP在Debign linux 上用7z测试CPU性能,惊讶,7z还有这功能。 赶快打开手边的电脑,看看 Windows 上的 7z 有没有这功能,一用,果然有这个功能。 以前想知道CPU性能就只能装些 XX大师,现在有了这个小巧的工具,知道参考数值就很方便了…...
高数
1 求 \(\lim_{n\to\infty}\left(1-\frac 1n\right)^{n^2}\) 解: 首先证明 \(\lim_{n\to\infty}\left(1-\frac 1n\right)^{n}=e^{-1}\)。 \[\begin{align*} \lim_{n\to\infty}\left(1-\frac 1n\right)^{n} &=\lim_{n\to\infty}\left[\left(1-\frac 1n\right)^{(n-1)}\right…...
P5666 [CSP-S2019] 树的重心
分为 \(x \ne rt\) 和 \(x = rt\) 两种情况计算. 对于第一种情况,不难发现我们合法的裁减下来的连通块大小是在一个区间范围之内的,于是 DFS 时用一棵树状数组修改即可(因为这个大小可能是子树大小可能是子树外大小,这取决于你一条祖先链有哪些点),但子树内的 siz 可能会被记入…...
Java运行机制
Java 程序运行机制 编译型(compile) 解释型 程序运行机制 ...
除自身以外数组的乘积-leetcode
题目描述 给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂度内完成此题。 示例 1: …...
【2022】SDRZ夏令营游记
为什么2022的游记会在2025年发? 因为感觉洛谷博客快扛不住了,决定开始搬运。今天是夏令营最后一天了,在机房里坐不住了,写篇游记来纪念一下。 day0: 这天是gryz65级三个校区的信竞同学第一次大会师。我成功与一区同学面基,线下见面和在网络上的印象完全不一样(《关于why…...
[论文笔记/评估方法] RELIABLE AND DIVERSE EVALUATION OF LLM MEDICAL KNOWLEDGE MASTERY
RELIABLE AND DIVERSE EVALUATION OF LLM MEDICAL KNOWLEDGE MASTERY该文章于2025年发表在ICLR(CCF A),早在2024年9月发布在arxiv。 文章地址:Reliable and Diverse Evaluation of LLM Medical Knowledge Mastery arXiv:[2409.14302] Reliable and diverse evaluation of …...
本地VMware Workstation Pro的rhel-server-7.9-x86_64服务器配置本地源
1. 安装好VMware Workstation Pro以及rhel-server-7.9-x86_64-dvd.iso后 2. 先对VMware Workstation 进行虚拟机关机 3. 对虚拟机的CD/DVD(SATA) 勾选设备状态为启动时连接,以及连接中勾选使用ISO镜像文件,为本地的rhel-server-7.9-x86_64-dvd.iso路径 4. 接下来就按如下操作…...
2025年十大AI网站构建工具:专家评测与推荐!
2025年,软件开发领域迎来一个关键转折点。随着 AI 技术的飞速发展,传统的网站或应用构建障碍正逐渐消失。市场上涌现出大量功能强大的工具,每一个都号称是您所需要的最佳 AI网站构建器 或 网站生成器。 然而,对于开发者、创业者乃至普通初学者而言,面对如此多的选择可能会…...
扫描线乱谈
扫描线乱谈前置知识 离散化,线段树 扫描线 首先假设你有n个矩形。如果直接暴力求解这些矩形的覆盖面积肯定不行,这时就要用扫描线算法。 假设有一根线,从下往上扫描:把每个小矩形分成很多不同的块,高是扫过的距离,那个位置没有被覆盖高就是0。显然答案就是高宽的和。 每次…...
详细介绍:量子计算学习(第十四周周报)
详细介绍:量子计算学习(第十四周周报)pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", monospace !import…...
视频播放时切出页面视频暂停(亲测可用)
视频播放时切出页面视频暂停(亲测可用)谷歌浏览器方法:视频播放网页,右键—检查—Elements—Event Listeners—找到blur,点开小三角,remove掉所有子元素...
VulkanAPI细节梳理1
1. PSOPipeline State Object,管线状态对象)? PSO 是 Vulkan 的核心概念之一,它是一个包含了渲染所需几乎所有状态的、不可变的对象。你可以把它想象成一台高度可配置的工业机器(GPU)的完整配置方案。在传统 API(如 OpenGL)中,你可以在运行时动态地、单独地修改各种状…...
cf773
D. Perishable Roads 题意: 有一个 \(n\) 个点的图,对于每两个点 \((i,j)\) 之间都有一条长度为 \(w_{i,j}\) 的无向边。 给你一个点 \(t\),你需要构造一棵以 \(t\) 为根的生成树,使得 \(\sum_{i=1}^n s(i,t)\) 尽量小。\(s(i,t)\) 为 \(i\sim t\) 的树上路径上的最小权值。…...
(简记)一类区间覆盖问题 珂朵莉树 ODT
简介与实现方法 该结构是通过 STL set 来维护存储相同颜色(相同值)连续段的暴力数据结构,需要在 set 中存储若干个三元组 \((l,r,k)\) 表示 \([l,r]\) 的所有颜色(值)都是 \(k\)。 它的使用条件是数据随机。我们把区间覆盖或群体赋值称为区间推平操作,如果该操作较多单一…...
5 事务隔离级别与锁机制
事务是由一组SQL语句组成的逻辑处理单元, 事务具有ACID 属性。原子性(Atomicity) :事务是一个原子操作单元,其对数据的修改,要么全都执行,要么全都不执行。 一致性(Consistent) :在事务开始和完成时,数据都必须保持一致状态。这意味着所有相关的数据规 则都必须应用于事务的修…...
我向编程世界宣布的第一声
Hello World随便新建一个文件夹,,存放代码 新建一个java文件文件后缀名为.java Hello.java 【注意点】系统可能没有显示文件后缀名,我们需要手动打开3.编写代码 public class Hello{public static void main(String[] args){System.out.print("Hello,World!");} }…...
意大利 公证 海牙认证速度 单号 双号
支付宝小程序 领事服务中心 那里(对应北京的领事) 比较慢,审核要一周,邮寄过去再寄回来又要一周。总共两周。可以接受单号 微信 山东外事 小程序 (对应济南的领事,只接受山东内的公证)审核很快,一天就审核通过,然后,邮寄过去再寄回来要一周。总共一周就行。必须要双号…...
Linux命令学习笔记
cd命令 1.切换上级目录 cd ..2.切换到当前用户主目录 cd ~ 3.切换上两级目录 cd ../..4.进入当前目录 cd . cat命令 1.查看文件 cat test.txt 2.查看文件并展示行号空行展示 cat -n test.txt 3.查看文件并展示行号,空行不转式 cat -b test.txt 4.查看多个文件 cat test.txt…...
网络安全需要真正的承诺而非表面功夫
本文探讨企业网络安全的核心问题——真正的组织承诺。作者指出许多企业仅采取半吊子安全措施,强调网络安全需要从企业文化到软件开发方式的全面变革,而非依赖外部工具或培训。文章分析了安全厂商解决方案的局限性,并提出改变游戏规则的思考方向。在我上一篇文章中,我谈到我…...
想成为AI绘画高手?打造独一无二的视觉IP!Seedream 4.0 使用指南详解,创意无界,效率翻倍!
想成为AI绘画高手?打造独一无二的视觉IP!Seedream 4.0 使用指南详解,创意无界,效率翻倍!想成为AI绘画高手?打造独一无二的视觉IP!Seedream 4.0 使用指南详解,创意无界,效率翻倍! AI-Compass 致力于构建最全面、最实用、最前沿的AI技术学习和实践生态,通过六大核心模…...
完整教程:液氮低温恒温器的应用领域
完整教程:液氮低温恒温器的应用领域pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", monospace !important;…...
轮转数组-leetcode
题目描述 给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。 示例 1: 输入: nums = [1,2,3,4,5,6,7], k = 3 输出: [5,6,7,1,2,3,4] 解释: 向右轮转 1 步: [7,1,2,3,4,5,6] 向右轮转 2 步: [6,7,1,2,3,4,5] 向右轮转 3 步: [5,6,7,1,2,3,4]示例 2: 输…...
CF1864G Magic Square
题面:(粘自洛谷) CF1864G Magic Square 题目描述 Aquamoon 有一个魔方,可以看作一个 \(n \times n\) 矩阵,矩阵的元素构成数字的排列 $1, \ldots, n^2 $ 。 Aquamoon 可以对矩阵执行两种操作:行移位,即将矩阵的整行向右移动几个位置(至少 $ 1 $ 且最多 $ n-1 $ )。 超出…...
OI TRICKS
位运算 每一位是独立的,可以拆开处理 \(a, b \in \{0, 1\}\),则xor and or\(a \oplus 1 = 1- a\) \(a \ \text{and} \ 0 = 0\) \(a \ \text{or} \ 1 = 1\)\(a \oplus 0 = a\) \(a \ \text{and} \ 1 = a\) \(a \ \text{or} \ 0 = a\)$a \oplus b = a + b - 2ab $ \(a \ \t…...
day37大模型程序开发-GraphRAG理论
RAG基本回顾实现流程准备原始的知识库(一个一个的文件组成) 将知识库文件内容进行读取(完整的字符串) 分块处理(新知识库:一段一段的文本字符串组成) 向量转换:将每一段文本chunk转换成向量(向量模型) 将向量数据存储到向量数据库 接受用户的提问,将用户提问转换成向…...
G
int a[1000001]; int top=-1;//栈为空 void push(int num) { a[++top]=num; } void pop() { printf("%d ", a[top--]); }//减1出栈 int main() { int n, i; int b[1000001]={0}; int c[1000001]={0}; scanf("%d", &n); for(i=0;i<n;i++)scanf("…...
AI Compass前沿速览:Nano Bananary、MCP Registry、通义DeepResearch 、VoxCPM、InternVLAM1具身机器人
AI Compass前沿速览:Nano Bananary、MCP Registry、通义DeepResearch 、VoxCPM、InternVLAM1具身机器人AI Compass前沿速览: AI-Compass 致力于构建最全面、最实用、最前沿的AI技术学习和实践生态,通过六大核心模块的系统化组织,为不同层次的学习者和开发者提供从完整学习路…...
day3536大模型应用开发-模型微调框架
为什么需要微调? 在开始学习微调之前,大家首先还是要搞清楚为什么要微调?在什么情况下需要微调?让模型更懂“专业话”:通用模型就像一个“万事通”,它学过很多东西,但对一些特别专业的领域(比如医学、法律、金融)可能不会特别精通。通过微调,我们可以给模型“补课”,…...
使用NVM管理Node.js版本
🍁简介 在当前日常前端开发中,不同项目可能依赖于不同版本的Node.js。 一个项目可能需要Node.js 14,而另一个项目可能需要Node.js 18甚至更高版本。 直接安装和卸载不同版本的Node.js不仅繁琐,而且容易导致环境混乱。 Node Version Manager NVM 是一个命令行工具,允许在同…...
day12-Trae之一键换脸APP开发02
今日内容 1 Trae配置 # 1 之前就装过python解释器和JDK了 # 2 如果你电脑上没有任何编辑器,使用txt写代码,都可以可以运行pyton或java的项目# 3 IDE只是个快速写代码的软件,如果没装python解释器和JDK---》代码运行不了Trae Pycharm Androidstudio VScode 都叫编辑器 简称ID…...
day35大模型应用开发-模型微调
为什么需要微调? 在开始学习微调之前,大家首先还是要搞清楚为什么要微调?在什么情况下需要微调?让模型更懂“专业话”:通用模型就像一个“万事通”,它学过很多东西,但对一些特别专业的领域(比如医学、法律、金融)可能不会特别精通。通过微调,我们可以给模型“补课”,…...
P6631 [ZJOI2020] 序列 题解
很好的贪心题。 考虑从左到右枚举每个位置,每次在右边添加一个数时更行答案。 容易想到记录当前前缀可以继续向右延伸的 \(1,2,3\) 操作的个数。记当前需要添加的数为 \(i\),用 \(c,x,y\) 分别表示可以继续向右延伸(从 \(\le i-1\) 的位置)的三种操作的个数:连续区间、奇偶…...
初始化一个rust环境
初始化一个rust环境初始化一个rust环境 rust 安装工具依赖入门 - Rust 程序设计语言一门帮助每个人构建可靠且高效软件的语言。 https://www.rust-lang.org/zh-CN/learn/get-startedrustup 环境变量 RUSTUP_DIST_SERVER : https://mirrors.ustc.edu.cn/rust-static RUSTUP_UPDA…...
编程里边有好多不容易触及的知识点
可能是因为不是原生土长的内容,编程里边有很多没有办法合情理解的领域。框架是其中一个,类似的还有 窗口库,还有好多其它东西。以前刚开始学窗口的时候,总是觉得没办法进行。周围的同学大概都是 拿过来用就可以,创建一个frame增加些lable 写一些事件。这些内容,相当于引用…...
25.9.18随笔联考总结
考试 通读题面,发现前两道是签。然后开做,饭堂,最后花费大部分时间过掉。后面两道题都不会。寄寄。 估计:100+100+0+0。实际:100+100+0+0。 有人藏分,素质有待提高! 改题+总结 T3 需要看出无限制的方案数对应卡特兰数,然后我没有推出来,并且也没有去打表找规律。感觉自…...
漏洞详解--文件上传 如何花样绕过?!
一、漏洞原理 1.1 核心 文件上传漏洞,顾名思义,将攻击者将恶意文件上传到服务器,服务器将恶意文件解析,攻击就达成了。 1.2 漏洞详解 文件上传漏洞非常好理解,有三个关键点,一是上传文件,二是找到文件上传的路径,三是使恶意文件得到解析。 假设一个系统没有防御(后面会…...
使用Windows客户端访问EDA环境的NFS共享
在IC设计环境中, 也总是会有Windows操作系统的开发服务器或者客户端需要使用IC设计平台中Linux主机使用的NFS服务器。 使用者也是IC设计团队中的一员,可能出于设计工具的原因, 他/她的部分工作必须在Windows中完成, 同时也需要保持NFS目录的权限体系,不能为了这少量的Wind…...
Day03-1
public class HelloWorld { public static void main(String[] args) { String teacher = "David"; System.out.println("Hello World"); } //有趣的代码注释 //单行注释 //输出一个Hello,World! //多行注释 :可以注释一段文字 /注释/ /* 我是多行注释 我…...
使用php -S 127.0.0.1:8000 新建php服务
php -S 127.0.0.1:8000 启动服务后 当前坐在目录下的所有文件都可以在浏览器上以 http://127.0.0.1/目录/文件名称 的形式访问 比如: 浏览器访问 http://127.0.0.1/upload_files.php 就会直接调用当前目录 upload_files.php 浏览器访问 http://127.0.0.1/ims/abc.png 就会打开…...
Day03
强类型语言 所有变量都需要定义后才能使用,Java,C++ 弱类型语言 Javascript 数据类型(JAVA) 基本类型 数值类型字符类型 char 占两个字节 浮点类型(小数)float 占四个字节 double 占八个整数类型byte 占一字节 short 占两字节 int 占四字节 long 占八字节boolean类型 占一…...
完整教程:从“我店”模式看绿色积分电商平台的困境与破局
完整教程:从“我店”模式看绿色积分电商平台的困境与破局pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", m…...
Java第三周课前思考
什么样的方法应该用static修饰?不用static修饰的方法往往具有什么特性?Student的getName应该用static修饰吗?完成独立功能或创建类的实例或对类级别的属性进行操作的方法应该用static修饰。 不用static修饰的方法往往具有依赖实例状态、通过实例调用、可访问静态变量和方法、…...
Java的安装及卸载
卸载JDK删除java的安装目录 删除JAVA_HOME(环境配置中) 删除path下关于java的目录(环境配置中) cmd中查找java -version是否仍存在安装JDK百度搜索JDK8,找到下载地址 同意协议 下载电脑对应的版本 双击安装JDK 记住安装的路径 配置环境变量我的电脑-->右键-->属性 环…...
题解:P13882 [蓝桥杯 2023 省 Java A] 小蓝的旅行计划
挺可爱的反悔贪心,乍一看没看出和旅行家的预算的区别,甚至做完才发现不一样的说。 正文 首先我们可以将操作分为两个部分。分别是用油操作和加油操作。 用油 有一个简单的贪心策略,用油的时候首先使用最便宜的油,这点显然。 此外,如果当前油箱里所有油都不能到达下一站,自…...
实用指南:订阅式红队专家服务:下一代网络安全评估新模式
实用指南:订阅式红队专家服务:下一代网络安全评估新模式pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", m…...