开散列哈希表。。。。。。
#include<iostream>
#include<memory>
#include<vector>
#include<string>
#include<cassert>
using std::vector, std::cout, std::endl, std::cin;
using std::string, std::destroy_at,std::construct_at;
//哈希表使用的类的声明
template<class Key, class Value>
class Hash_Table;
template<class Key, class Value>
struct pair;
template<class Key, class Value>
struct _hash_node_;
template<class Key, class Value>
class iterator;
//下面三个是哈希函数
//int版本
size_t BKDHash(const int& key) noexcept
{
return static_cast<size_t>(key);
}
//string版本
size_t BKDHash(const string& key) noexcept
{
size_t seed = 131, hash = 0, siz = key.size();
for (size_t i = 0; i < siz; ++i)
{
hash = hash * seed + key[i];
}
return hash;
}
//char版本
size_t BKDHash(const char& key) noexcept
{
return static_cast<size_t>(key);
}
//素数表
const size_t PRIME_COUNT = 28;
const size_t prime_list[PRIME_COUNT] = { 53ul, 97ul, 193ul, 389ul, 769ul,
1543ul, 3079ul, 6151ul, 12289ul, 24593ul,
49157ul, 98317ul, 196613ul, 393241ul, 786433ul,
1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul,
50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul,
1610612741ul, 3221225473ul, 4294967291ul };
//pair类型,存放键值对
template<class Key, class Value>
struct pair
{
Key key;
Value value;
};
//哈希结点类型
template<class Key, class Value>
struct _hash_node_
{
pair<Key, Value> _data;
_hash_node_<Key, Value>* _next;
};
//哈希迭代器类型
template<class Key, class Value>
class iterator
{
public:
using _pnode = _hash_node_<Key, Value>*;
using _node = _hash_node_<Key, Value>;
using _ptable = Hash_Table<Key, Value>*;
iterator(const _pnode p , const _ptable t )noexcept :_p(p), _t(t) {}
iterator(const iterator& rhs)noexcept :_p(rhs._p), _t(rhs._t) {}
const iterator& operator=(const iterator& rhs) noexcept
{
if (this != &rhs)
{
_p = rhs._p;
_t = rhs._t;
}
return *this;
}
~iterator()noexcept {}
//对迭代器解引用返回pair类型
pair<Key, Value>& operator*()const noexcept
{
assert(_p);
return _p->_data;
}
//对迭代器使用指针操作符返回pair指针
pair<Key, Value>* operator->()const noexcept
{
assert(_p);
return &(_p->_data);
}
//自增函数
iterator& operator++()noexcept
{
assert(_t);
if (!_p)
{
return *this;
}
if (_p->_next)
{
_p = _p->_next;
return *this;
}
else
{
size_t siz = _t->_table.size();
size_t index = (BKDHash(_p->_data.key) % siz) + 1;
for (; index < siz; ++index)
{
if (_t->_table[index])
{
_p = _t->_table[index];
return *this;
}
}
_p = nullptr;
return *this;
}
}
const iterator operator++(int)noexcept
{
iterator tmp(*this);
++(*this);
return tmp;
}
bool operator==(const iterator& rhs) const noexcept
{
return _p == rhs._p && _t == rhs._t;
}
bool operator!=(const iterator& rhs) const noexcept
{
return !(*this == rhs);
}
private:
_pnode _p;
_ptable _t;
};
//哈希表
template<class Key, class Value>
class Hash_Table
{
public:
friend class iterator<Key,Value>;
using _pnode = _hash_node_<Key, Value>*;
Hash_Table()noexcept :_n(0) {}
~Hash_Table()noexcept
{
clear();
}
void clear()noexcept
{
size_t siz = _table.size();
_pnode pt = nullptr, pre = nullptr;
for (size_t i = 0; i < siz; ++i)
{
pt = _table[i];
for (; pt; )
{
pre = pt;
pt = pt->_next;
_destroy_(pre);
}
_table[i] = nullptr;
}
_table.resize(0);
_n = 0;
}
void insert(const pair<Key, Value>& val) noexcept
{
if (_find(val))
{
return;
}
if (_table.empty())
{
_table.resize(53ul, nullptr);
}
if ((static_cast<double>(_n) / static_cast<double>(_table.size())) > 0.75)
{
size_t siz = _table.size();
size_t nxt = _get_next_prime(siz);
if (nxt == 0)
{
return;
}
vector<_pnode> new_table(nxt, nullptr);
_pnode pt = nullptr;
for (size_t i = 0; i < siz; ++i)
{
pt = _table[i];
if (pt)
{
new_table[BKDHash(pt->_data.key) % nxt] = pt;
_table[i] = nullptr;
}
}
_table.swap(new_table);
}
size_t index = BKDHash(val.key) % _table.size();
_pnode new_node = static_cast<_pnode>(calloc(1, sizeof(_hash_node_<Key, Value>)));
if (new_node)
{
construct_at(&new_node->_data.key, val.key);
construct_at(&new_node->_data.value, val.value);
new_node->_next = _table[index];
_table[index] = new_node;
++_n;
}
}
size_t bucket_size()const noexcept
{
size_t count = 0, siz = _table.size();
for (size_t i = 0; i < siz; ++i)
{
if (_table[i])
{
++count;
}
}
return count;
}
void remove(const pair<Key, Value>& val) noexcept
{
if (_n == 0)
{
return;
}
size_t index = BKDHash(val.key) % _table.size();
_pnode pt = _table[index];
if (pt == nullptr)
{
return;
}
if (pt->_data.value == val.value)
{
_table[index] = pt->_next;
_destroy_(pt);
--_n;
}
else
{
_pnode prev = nullptr;
for (; pt;)
{
prev = pt;
pt = pt->_next;
if (pt && pt->_data.value == val.value)
{
break;
}
}
if (pt)
{
prev->_next = pt->_next;
_destroy_(pt);
--_n;
}
}
}
size_t size() const noexcept
{
return _n;
}
iterator<Key,Value> begin() noexcept
{
size_t siz = _table.size();
for (size_t i = 0; i < siz; ++i)
{
if (_table[i])
{
return iterator<Key,Value>(_table[i], this);
}
}
return iterator<Key,Value>(nullptr, this);
}
iterator<Key,Value> end() noexcept
{
return iterator<Key,Value>(nullptr, this);
}
void for_each() const noexcept
{
if (_n == 0)
{
return;
}
_pnode pt = nullptr;
size_t siz = _table.size();
for (size_t i = 0; i < siz; ++i)
{
pt = _table[i];
if (pt)
{
for (; pt; pt = pt->_next)
{
cout << pt->_data.key << " " << pt->_data.value << endl;
}
}
}
}
const vector<Value*> at(const Key& key)const noexcept
{
vector<Value*> tmp;
_pnode pt = _table[BKDHash(key) % _table.size()];
for (;pt;pt = pt->_next)
{
tmp.push_back(&pt->_data.value);
}
return tmp;
}
iterator<Key,Value> find(const pair<Key, Value>& pair) noexcept
{
return iterator<Key,Value>(_find(pair), this);
}
const vector<Value*> operator[](const Key& key)const noexcept
{
return at(key);
}
protected:
_pnode _find(const pair<Key, Value>& pair)const noexcept
{
if (_n == 0)
{
return nullptr;
}
size_t index = BKDHash(pair.key) % _table.size();
_pnode pt = _table[index];
for (; pt; pt = pt->_next)
{
if (pt->_data.value == pair.value)
{
return pt;
}
}
return nullptr;
}
size_t _get_next_prime(size_t cur)const noexcept
{
for (size_t i = 0; i < PRIME_COUNT; ++i)
{
if (prime_list[i] > cur)
{
return prime_list[i];
}
}
return 0;
}
void _destroy_(_pnode pt) noexcept
{
if (pt)
{
destroy_at(&pt->_data.key);
destroy_at(&pt->_data.value);
free(pt);
}
}
private:
vector<_pnode> _table;
size_t _n;
};
int main()
{
Hash_Table<char, int> t;
int a = 10;
for (char i = 'a'; i <= 'z'; ++i)
{
t.insert(pair<char, int>{i, a});
}
for (char i = 'A'; i <= 'Z'; ++i)
{
t.insert(pair<char, int>{i,a});
}
for (char i = 'A'; i <= 'Z'; ++i)
{
t.remove(pair<char, int>{i, a});
}
for (char i = 'a'; i <= 'z'; ++i)
{
t.remove(pair<char, int>{i, a});
}
for (char i = 'A'; i <= 'Z'; ++i)
{
t.insert(pair<char, int>{i, a});
}
for (char i = 'a'; i <= 'z'; ++i)
{
t.insert(pair<char, int>{i, a});
}
for (auto i = t.begin(); i != t.end(); ++i)
{
cout << i->key << " " << i->value << endl;
}
cout << t.size() << endl;
cout << t.bucket_size() << endl;
return 0;
}
Comments NOTHING