#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. uni-app 计算属性 computed

    功能:=>大于1000用kg表示 小于1000,用g表示 计算属性 计算属性必须是有一个返回值的哦 在html写被计算的值 在computed中去直接调用哈 <view> <t ...

  2. js正则手机号 验证

    注意一下 现在手机号第二位是不是 只有3 4 5 7 8这几个数, 如果还有请告诉我,否则这个正则表达式式错误的. <div id="app"> <el-inpu ...

  3. vue过滤器(filter)的使用

    过滤器分全局过滤器和局部过滤器 <div id="app"> <p>电脑价格:{{price | addPriceIcon}}</p> < ...

  4. 【代码分享】使用 terraform, 在 Let's Encrypt 上申请托管在 cloudflare 上的域名对应的证书

    作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu Github 公众号:一本正经的瞎扯 运行的流程可以抽象为上图. 直接贴代码: letsencr ...

  5. 【VictoriaMetrics源码阅读】vm中仿照RoaringBitmap的实现:uint64set

    作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu 公众号:一本正经的瞎扯 正文 VictoriaMetrics中使用uint64类型来表示一个Me ...

  6. 最新 Hugging Face 强化学习课程(中文版)来啦!

    人工智能中最引人入胜的话题莫过于深度强化学习 (Deep Reinforcement Learning) 了,我们在 2022 年 12 月 5 日开启了<深度强化学习课程 v2.0>的课 ...

  7. Similarities:精准相似度计算与语义匹配搜索工具包,多维度实现多种算法,覆盖文本、图像等领域,支持文搜、图搜文、图搜图匹配搜索

    Similarities:精准相似度计算与语义匹配搜索工具包,多维度实现多种算法,覆盖文本.图像等领域,支持文搜.图搜文.图搜图匹配搜索 Similarities 相似度计算.语义匹配搜索工具包,实现 ...

  8. centos7.9离线升级openssl和openssh9.2

    前言 最近有几台服务器漏扫出了关于openssh的漏洞,升级完后顺便记录一下. 环境 CentOS Linux release 7.9.2009 (Core) 开始升级 准备工作 下载安装包: zli ...

  9. Windows 7 Ultimate with Service Pack 1 (x64)

    Windows 7 Ultimate with Service Pack 1 (x64) 链接:https://pan.baidu.com/s/1ZHODDFlJPLQ3ydxZ4rfc3g 提取码: ...

  10. MarkDown文件插入公式(常用格式)

    1.插入公式 markdown支持插入公式,书写公式需要按照特定格式来写,涉及到希腊字母.符号.角标.基本语法等内容需要熟悉, 1.1 句中插入公式 表达式前后插入$即可 ,比如$\alpha$,显示 ...