STL-unordered_hashtable模拟实现
#pragma once #include<vector>
#include<string>
#include<iostream>
using std::cout;
using std::endl;
using std::pair;
using std::make_pair; namespace HashBucket
{ template<class T>
struct HashNode
{
HashNode* _next = nullptr;
T _data; HashNode(const T& data)
:_data(data)
{} }; //HashNode_end //见27.
template<class K>
struct HashFunc
{
size_t operator()(const K& key)
{
return key;
}
};
template<>
struct HashFunc<std::string>
{
size_t operator()(const std::string& s)
{
size_t ret = 0;
for (auto ch : s)
{
ret += ch;
ret *= 31;
}
return ret;
}
}; //根据声明顺序,使用下面的类需要前置声明
template<class K, class T, class keyOfT, class Hash >
class HashTable; template<class K , class T, class Ref, class Ptr, class keyOfT,class Hash>
struct __Hash_iterator
{
//迭代器怎么写?
/**
* 1.迭代器需要什么模板类?
* -> 先写符号重载,看需要什么:写了++,需要结点,哈希表
*
* 2.需要什么函数重载?
* -> ++ . -- , != , * , -> ,
*
* 3.写外部函数调用,看需要什么
*/ typedef __Hash_iterator<K, T, T&, T*, keyOfT, Hash > iterator;
typedef __Hash_iterator<K, T, Ref, Ptr, keyOfT, Hash > Self; typedef HashNode<T> node;
typedef HashTable<K, T, keyOfT,Hash> HashTable; node* _node;
const HashTable* _ht; //不允许修改 __Hash_iterator(node* node, const HashTable* ht) //普通构造函数 --- 绝对不能用引用,因为迭代器是有可能会修改指针,使用引用可能会改崩原指针,
:_node(node)
,_ht(ht)
{} __Hash_iterator(const iterator& it)
:_node(it._node)
,_ht(it._ht)
{} Ref operator*()
{
return _node->_data;
}
Ptr operator->()
{
return &_node->_data;
}
bool operator!=(const Self& s)
{
return _node != s._node;
} Self& operator++() //迭代器++返回什么? 返回新的迭代器
{
/** 迭代器怎么++ ?
* 条件:
*
* 1.当前结点为空
* a.循环,计算哈希值,找下一个不为空的数组
* 循环出口:1.哈希值超过数组最大长度 2.找到不为空的元素
* 循环入口:1
* 循环结束后:返回空--没找到
*
* 2.当前结点非空
* a.返回下一个位置
*
*/
Hash hash;
keyOfT kot;
if (_node->_next) //_node&& _node->_next 迭代器不会为空,直到end为止,end再加就崩了,看库怎么限制法
{
_node = _node->_next; }
else
{
size_t hashi = hash(kot(_node->_data))% _ht->_tables.size();//计算哈希值
++hashi;//这个已经是空了,从下一个开始,
size_t sz = _ht->_tables.size();
while (hashi < sz)
{
if (_ht->_tables[hashi])
{
_node = _ht->_tables[hashi];
break;
}
++hashi;
}
if (sz == hashi)
{
_node = nullptr;
}
}
return *this;
} //operater++_end; }; //iterator_end; template<class K, class T,class keyOfT,class Hash >
class HashTable
{
template<class K, class T, class Ref, class Ptr, class keyOfT, class Hash>
friend struct __Hash_iterator; public:
typedef HashNode<T> node;
typedef __Hash_iterator<K, T, T&, T*, keyOfT, Hash> iterator;
typedef __Hash_iterator<K, T, const T&,const T*, keyOfT, Hash> const_iterator;
private:
size_t _n = 0;
std::vector<node*> _tables; public:
iterator begin()
{
node* cur = nullptr;
for (size_t i = 0; i < _tables.size(); ++i)
{
if (_tables[i])
{
cur = _tables[i];
break;
}
}
return iterator(cur,this);
} // begin_end; iterator end()
{
return iterator(nullptr, this);
} const_iterator begin() const
{
return begin(); //类型转换即可
} const_iterator end() const
{
return end(); //类型转换即可
} ~HashTable()
{
for (auto& cur : _tables)
{
while (cur)
{
node* next = cur->_next;
delete cur;
cur = next;
}
}
//析构,只需要析构主动申请的空间,栈空间不需要,防止内存泄漏
} size_t GetNextPrime(size_t prime)
{
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
};
size_t i = 0;
for ( ;i < __stl_num_primes; ++i)
{
if (__stl_prime_list[i] > prime)
return __stl_prime_list[i];
} return __stl_prime_list[i];
} pair<iterator,bool> insert(const T& data)
{
keyOfT kot;
Hash hash;
iterator it = find(kot(data));
if (it!=end())
{
return make_pair(it,false);
} if (_n == _tables.size())
{
size_t newsize = GetNextPrime(_tables.size()); std::vector<node*> newht(newsize, nullptr); for (auto& cur : _tables)
{
while (cur)
{
node* next = cur->_next; size_t hashi = hash(kot(cur->_data)) % newht.size(); cur->_next = newht[hashi];
newht[hashi] = cur; cur = next;
}
}
_tables.swap(newht);
}
size_t hashi = hash(kot(data)) % _tables.size(); node* newnode = new node(data);
newnode->_next = _tables[hashi];
_tables[hashi] = newnode;
++_n; return make_pair(iterator(_tables[hashi],this),true);
}//insert_end iterator find(const K& key)
{
keyOfT kot;
Hash hash; if (_n == 0)
{
return end();
}
size_t hashi = hash(key) % _tables.size();
node* cur = _tables[hashi]; while (cur)
{
if (kot(cur->_data) == key)
{
break;
}
cur = cur->_next;
} return iterator(cur,this);
} //find_end bool erase(const K& key) //可以返回bool,库中返回 1或0 和 迭代器,选择bool也可以
{
keyOfT kot; Hash hash;
size_t hashi = hash(key) % _tables.size(); node* cur = _tables[hashi];
node* prev = nullptr;
while (cur)
{
if (kot(cur->_data) == key)
{
if (!prev)
{
_tables[hashi] = cur->_next;
}
else
{
prev->_next = cur->_next;
}
delete cur; return true;
}
prev = cur;
cur = cur->_next;
} return false;
}//erase_end size_t MaxBucketSize()
{
size_t max = 0;
for (size_t i = 0; i < _tables.size(); ++i)
{
auto cur = _tables[i];
size_t size = 0;
while (cur)
{
++size;
cur = cur->_next;
} if (size > max)
{
max = size;
}
} return max;
} };//HashBucket_end }
STL-unordered_hashtable模拟实现的更多相关文章
- <泛> STL - vector 模拟实现
今天为大家带来一个模拟STL-vector的模板实现代码. 首先看一下测试结果,之后再为大家呈现设计 测试效果 测试代码 #include<iostream> #include<ve ...
- 洛谷 P1739 表达式括号匹配【STL/stack/模拟】
题目描述 假设一个表达式有英文字母(小写).运算符(+,-,*,/)和左右小(圆)括号构成,以"@"作为表达式的结束符.请编写一个程序检查表达式中的左右圆括号是否匹配,若匹配,则返 ...
- <泛> STL - stack 模拟实现
今天,看C++Template的时候看到那人写了一个Stack,于是乎,手痒,自己也写了一个,在拜读了STD文件和C++模板元编程某些小节之后,你们就看到了这篇代码. 经过上述一番经历之后,我重新写了 ...
- STL string 模拟
下面的代码来自c++ primer plus第5版第12章,书中代码写的非常好: // string1.h -- fixed and augmented string class definition ...
- UVa 12219 Common Subexpression Elimination (stl,模拟,实现)
一般来说,把一颗子树离散成一个int,把一个结点的字符离散成一个int会方便处理 直接map离散.当然一个结点最多只有4个小写字母,也可以直接编码成一个27进制的整数,舍掉0,为了区分0和0000. ...
- 【STL+模拟】UVa 506 - System Dependencies
System Dependencies Components of computer systems often have dependencies--other components that m ...
- hiho一下 第四十七周 拓扑排序一 【静态数组链式前向星存储结构实现 + 拓扑跳出 】
题目1 : 拓扑排序·一 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 由于今天上课的老师讲的特别无聊,小Hi和小Ho偷偷地聊了起来. 小Ho:小Hi,你这学期有选什么 ...
- 【数据结构】洛谷2019 OI春令营 - 普及组 作业
[P3662][USACO17FEB]Why Did the Cow Cross the Road II S 求解连续的k个数的最大值,利用前缀和维护即可. #include<bits/stdc ...
- 基于各种基础数据结构的SPFA和各种优化
一.基于各种数据结构的SPFA 以下各个数据均为不卡SPFA的最短路模板:P3371 [模板]单源最短路径(弱化版)的测试时间 1.STL队列:用时: 1106ms / 内存: 8496KB #inc ...
- LeetCode双周赛#36
1604. 警告一小时内使用相同员工卡大于等于三次的人 题目链接 题意 给定两个字符串数组keyName和keyTime,分别表示名字为keytime[i]的人,在某一天内使用员工卡的时间(格式为24 ...
随机推荐
- Redis极简教程
简介 Redis 是用C语言开发完全开源免费的,遵守BSD协议的,一个高性能的,key-value型的,NOSQL数据库. 特点 可以将内存中的数据持久化到硬盘中,重启的时候可以从硬盘中再次加载 拥有 ...
- ant-design-vue 表单验证详解
表单验证详解 <template> <!-- 第一个坑 :model="formState.youForm" 一定要写成这样 不要写成:model="f ...
- 从零开始匹配vim(1)——选项设置
前面我们算是对 vimscript 做了一个入门,并且实现了一个 输出 hello world 的语句.现在我们继续进行 vimscript 的学习. set语句 之前在介绍 vim 基础的时候,我们 ...
- TienChin-课程管理-展示课程列表
配置按钮权限 博主这里就不贴SQL了,自行手动添加一下吧. 更改表结构 ALTER TABLE `tienchin_course` MODIFY COLUMN `info` varchar(255) ...
- 【Java】ArrayList线程不安全的坑
问题复现: 使用Java的steam().paralleStream(),foreach()方法向ArrayList添加数据,导致ArrayList中出现空值,代码如下: public static ...
- TextBrewer:融合并改进了NLP和CV中的多种知识蒸馏技术、提供便捷快速的知识蒸馏框架、提升模型的推理速度,减少内存占用
TextBrewer:融合并改进了NLP和CV中的多种知识蒸馏技术.提供便捷快速的知识蒸馏框架.提升模型的推理速度,减少内存占用 TextBrewer是一个基于PyTorch的.为实现NLP中的知识蒸 ...
- 2.1 CE修改器:精确数值扫描
本关是CE修改器的第一关,用户需要通过 Cheat Engine 工具完成精确扫描值.在这个练习中,需要将一个特定的数值(健康值)改变为 1000.首先,要确保数值类型设置正确,默认的是2字节或4字节 ...
- 3.2 DLL注入:远程APC异步注入
APC(Asynchronous Procedure Call)异步过程调用是一种Windows操作系统的核心机制,它允许在进程上下文中执行用户定义的函数,而无需创建线程或等待OS执行完成.该机制适用 ...
- SDK多项目开发与联调
在SDK开发中,因为是往外提供的功能静态库,所以在开发的时候要验证开发的SDK是否功能正常,这里就需要做进行边开发边联调的工作. 下面使用的开发模式是创建一个WorkSpace工作工具,SDK项目和D ...
- 关于JAVA泛型数组类型擦除引发的问题及解决方案
先看如下一个DEMO示例代码:(其中doBatchGet被子类重写了1次) public abstract class BaseDemoService<T> { public String ...