#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模拟实现的更多相关文章

  1. <泛> STL - vector 模拟实现

    今天为大家带来一个模拟STL-vector的模板实现代码. 首先看一下测试结果,之后再为大家呈现设计 测试效果 测试代码 #include<iostream> #include<ve ...

  2. 洛谷 P1739 表达式括号匹配【STL/stack/模拟】

    题目描述 假设一个表达式有英文字母(小写).运算符(+,-,*,/)和左右小(圆)括号构成,以"@"作为表达式的结束符.请编写一个程序检查表达式中的左右圆括号是否匹配,若匹配,则返 ...

  3. <泛> STL - stack 模拟实现

    今天,看C++Template的时候看到那人写了一个Stack,于是乎,手痒,自己也写了一个,在拜读了STD文件和C++模板元编程某些小节之后,你们就看到了这篇代码. 经过上述一番经历之后,我重新写了 ...

  4. STL string 模拟

    下面的代码来自c++ primer plus第5版第12章,书中代码写的非常好: // string1.h -- fixed and augmented string class definition ...

  5. UVa 12219 Common Subexpression Elimination (stl,模拟,实现)

    一般来说,把一颗子树离散成一个int,把一个结点的字符离散成一个int会方便处理 直接map离散.当然一个结点最多只有4个小写字母,也可以直接编码成一个27进制的整数,舍掉0,为了区分0和0000. ...

  6. 【STL+模拟】UVa 506 - System Dependencies

    System Dependencies  Components of computer systems often have dependencies--other components that m ...

  7. hiho一下 第四十七周 拓扑排序一 【静态数组链式前向星存储结构实现 + 拓扑跳出 】

    题目1 : 拓扑排序·一 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 由于今天上课的老师讲的特别无聊,小Hi和小Ho偷偷地聊了起来. 小Ho:小Hi,你这学期有选什么 ...

  8. 【数据结构】洛谷2019 OI春令营 - 普及组 作业

    [P3662][USACO17FEB]Why Did the Cow Cross the Road II S 求解连续的k个数的最大值,利用前缀和维护即可. #include<bits/stdc ...

  9. 基于各种基础数据结构的SPFA和各种优化

    一.基于各种数据结构的SPFA 以下各个数据均为不卡SPFA的最短路模板:P3371 [模板]单源最短路径(弱化版)的测试时间 1.STL队列:用时: 1106ms / 内存: 8496KB #inc ...

  10. LeetCode双周赛#36

    1604. 警告一小时内使用相同员工卡大于等于三次的人 题目链接 题意 给定两个字符串数组keyName和keyTime,分别表示名字为keytime[i]的人,在某一天内使用员工卡的时间(格式为24 ...

随机推荐

  1. Orika JavaBean映射工具使用

    作者:京东零售 张宾 1.Orika是什么? Orika是一个简单.快速的JavaBean拷贝框架,它能够递归地将数据从一个JavaBean复制到另一个JavaBean,这在多层应用开发中是非常有用的 ...

  2. 【踩了一个坑】为什么 golang struct 中的 slice 无法原子赋值

    作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu Github 公众号:一本正经的瞎扯 有这样一个结构体: type MySt struct{ F ...

  3. 紧跟潮流,抓住趋势,跟上全民AI的节奏,开源IM项目OpenIM产品介绍,为AIGC贡献力量

    开源价值 高度自主.安全可控.开放自由,私有化部署,一切皆可控 透明度和可信度:开源软件的源代码是公开的,任何人都可以查看和检查代码,从而增强了软件的透明度和可信度.用户可以了解软件的内部结构和运作方 ...

  4. 数据挖掘机器学习[五]---汽车交易价格预测详细版本{模型融合(Stacking、Blending、Bagging和Boosting)}

    题目出自阿里天池赛题链接:零基础入门数据挖掘 - 二手车交易价格预测-天池大赛-阿里云天池 相关文章: 特征工程详解及实战项目[参考] 数据挖掘---汽车车交易价格预测[一](测评指标:EDA) 数据 ...

  5. 【scikit-learn基础】--『分类模型评估』之系数分析

    前面两篇介绍了分类模型评估的两类方法,准确率分析和损失分析,本篇介绍的杰卡德相似系数和马修斯相关系数为我们提供了不同的角度来观察模型的性能,尤其在不平衡数据场景中,它们更能体现出其独特的价值. 接下来 ...

  6. 网友感到担忧!iOS 17支持第三方应用商店:这下跟安卓没区别了

    苹果此前官宣将于6月6日召开WWDC2023大会,按照往年的惯例,在这次大会上将会推出下一代iOS系统,也就是iOS 17.最近国外有关iOS 17的爆料中提到,迫于欧盟法案压力,iOS 17或将支持 ...

  7. C语言中如何使两个整型变量计算出浮点型结果

    遭遇的问题 在学习时有一个课后题要求计算两个变量的加减乘除以及取余,想到除法可能会计算出小数,就用浮点型接收除法的结果 int a,b: double div; div = a / b; 但是算出来的 ...

  8. Build 和 Compile 区别

  9. CF1849

    传送门 A 氵 B 在吃了五次罚时后,我终于放弃了卡常优先队列,并发现:把余 \(0\) 看作余 \(k\),答案就是余数从大到小排列的,每种余数内部又按照下标排序. C 我为什么没想到哈希?自我检讨 ...

  10. NC21467 [NOIP2018]货币系统

    题目链接 题目 题目描述 在网友的国度中共有n种不同面额的货币,第i种货币的面额为a[i],你可以假设每一种货币都有无穷多张.为了方便,我们把货币种数为n.面额数组为a[1..n]的货币系统记作(n, ...