仿照SGI扩展中的hash_set和hash_map实现了下面两个简化的模板类。
她们的使用方法与stl中的容器类相似,支持插入,查找,删除,遍历等。
成员函数名称和语义基本与stl中的容器类一致。
迭代器的使用也与stl容器类的基本一致。
main.cpp中的代码是个简单的测试用例,我写的有点乱。
编译:g++ -g -W -Wall -Wextra -o mytest main.cpp
执行:./mytest
main.cpp:
==============================================
// 2012年 02月 13日 星期一 14:15:42 CST
// author: 李小丹(Li Shao Dan) 字 殊恒(shuheng)
// K.I.S.S
// S.P.O.T
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <unistd.h>
#include "shuheng_hash.h"
using namespace std;
void tst_hash();
void tst_hash1();
class hash {
public:
inline size_t operator ()(int k)
{
return k;
}
};
int main()
{
tst_hash();
tst_hash1();
return 0;
}
void tst_hash()
{
shuheng::hash_map<int, int, hash> myhash(7);
for(int i = 0; i < 65; ++i)
myhash.insert(make_pair(i, i));
cout << myhash.size() << endl;
sleep(1);
for(shuheng::hash_map<int, int, hash>::const_iterator p
= myhash.begin(); p != myhash.end(); ++p)
cout << p->first << "\t" << p->second << endl;
cout << "====================================\n";
sleep(1);
for(shuheng::hash_map<int, int, hash>::iterator p
= myhash.begin(); p != myhash.end(); ++p)
p->second *= 2;
for(shuheng::hash_map<int, int, hash>::const_iterator p
= myhash.begin(); p != myhash.end(); ++p)
cout << p->first << "\t" << p->second << endl;
cout << "====================================\n";
sleep(1);
shuheng::hash_map<int, int, hash>::iterator pos;
if((pos = myhash.find(38)) != myhash.end())
myhash.erase(pos);
for(shuheng::hash_map<int, int, hash>::const_iterator p
= myhash.begin(); p != myhash.end(); ++p)
cout << p->first << "\t" << p->second << endl;
cout << "====================================\n";
cout << myhash.size() << endl;
sleep(1);
for(shuheng::hash_map<int, int, hash>::iterator p
= myhash.begin(); p != myhash.end(); ++p)
myhash.erase(p);
cout << myhash.size() << endl;
for(int i = 0; i < 88; ++i)
myhash.insert(make_pair(i, i * 3));
for(shuheng::hash_map<int, int, hash>::const_iterator p
= myhash.begin(); p != myhash.end(); ++p)
cout << p->first << "\t" << p->second << endl;
cout << "====================================\n";
sleep(1);
myhash.clear();
shuheng::hash_map<int, int, hash> myhash1;
for(int i = 0; i < 17; ++i)
myhash1.insert(make_pair(i, i));
shuheng::hash_map<int, int, hash>::iterator p;
int i = 0;
for(p = myhash1.begin(); i < 16; ++p, ++i)
cout << p->first << "\t" << p->second << endl;
cout << "====================================\n";
sleep(1);
for(shuheng::hash_map<int, int, hash>::const_iterator pos = p; pos != myhash1.end(); --pos)
cout << pos->first << "\t" << pos->second << endl;
cout << "====================================\n";
sleep(1);
for(shuheng::hash_map<int, int, hash>::const_iterator p
= myhash1.begin(); p != myhash1.end(); p++)
cout << p->first << "\t" << p->second << endl;
cout << "====================================\n";
sleep(1);
i = 0;
for(p = myhash1.begin(); i < 16; p++, ++i)
cout << p->first << "\t" << p->second << endl;
cout << "====================================\n";
sleep(1);
for(shuheng::hash_map<int, int, hash>::const_iterator pos = p; pos != myhash1.end(); pos--)
cout << pos->first << "\t" << pos->second << endl;
cout << "====================================\n";
sleep(1);
if((p = myhash1.find(3)) != myhash1.end()) {
myhash1.erase(p++);
myhash1.erase(p--);
}
for(shuheng::hash_map<int, int, hash>::const_iterator pos = myhash1.begin(); pos != myhash1.end(); ++pos)
cout << pos->first << "\t" << pos->second << endl;
cout << "====================================\n";
}
class hash_fun {
public:
size_t operator ()(char *buf) const
{
size_t h = 0;
unsigned char *p = (unsigned char *)buf;
for(int i = 0; *p; ++i, ++p)
h += *p * 37 * i;
return h;
}
};
class hash_cmp {
public:
bool operator ()(const char *p1, const char *p2) const
{
return strcmp(p1, p2) == 0;
}
};
void tst_hash1()
{
shuheng::hash_set<char *, hash_fun, hash_cmp> myhash;
FILE *fp;
if((fp = fopen("./main.cpp", "r"))) {
char buf[2048];
while(fgets(buf, sizeof(buf), fp)) {
int len = strlen(buf);
if(len < 2) continue;
char *p = new char [len];
strncpy(p, buf, len - 1);
p[len-1] = 0;
pair<shuheng::hash_set<char *, hash_fun,
hash_cmp>::iterator, bool> ret
= myhash.insert(p);
if(!ret.second)
delete [] p;
}
fclose(fp);
}
for(shuheng::hash_set<char *, hash_fun, hash_cmp>::iterator p
= myhash.begin(); p != myhash.end();
++p)
cout << *p << endl;
if((fp = fopen("./main.cpp", "r"))) {
char buf[2048];
while(fgets(buf, sizeof(buf), fp)) {
int len = strlen(buf);
if(len < 2) continue;
buf[len-1] = 0;
shuheng::hash_set<char *,
hash_fun, hash_cmp>::iterator p;
if((p = myhash.find(buf)) == myhash.end())
cout << "can't find!" << endl;
}
fclose(fp);
}
for(shuheng::hash_set<char *, hash_fun, hash_cmp>::iterator p
= myhash.begin(); p != myhash.end();
++p)
delete [] *p;
myhash.clear();
}
=============================================
shuheng_hash.h:
=============================================
// 2012年 02月 09日 星期四 08:49:48 CST
// author: 李小丹(Li Shao Dan) 字 殊恒(shuheng)
// K.I.S.S
// S.P.O.T
#ifndef SHUHENG_HASH_H
#define SHUHENG_HASH_H
#include <utility>
#include <functional>
#include <cstring>
#include <cassert>
using std::pair;
#define DEFAULT_HASH_SIZE 1021
namespace shuheng {
//==================hash_map=====================
//template: Key, Value, hash Function, Compare
template <class K, class V, class F, class C>
class hash_map;
template <class K, class V, class F, class C>
class map_iterator;
template <class K, class V, class F, class C>
inline static bool operator ==(
const map_iterator<K, V, F, C> &,
const map_iterator<K, V, F, C> &);
template <class K, class V, class F, class C>
inline static bool operator !=(
const map_iterator<K, V, F, C> &,
const map_iterator<K, V, F, C> &);
template <class K, class V, class F, class C>
class map_node {
public:
friend class hash_map<K, V, F, C>;
friend class map_iterator<K, V, F, C>;
private:
map_node(const pair<K, V> &);
private:
pair<const K, V> key_value;
map_node *slot_next;
map_node *slot_prev;
map_node *list_next;
map_node *list_prev;
};
template <class K, class V, class F, class C>
map_node<K, V, F, C>::map_node(const pair<K, V> &kv)
:key_value(kv), slot_next(0),
slot_prev(0), list_next(0), list_prev(0)
{
}
template <class K, class V, class F, class C>
class map_iterator {
public:
friend class hash_map<K, V, F, C>;
friend bool operator ==<K, V, F, C>(
const map_iterator<K, V, F, C> &,
const map_iterator<K, V, F, C> &);
friend bool operator !=<K, V, F, C>(
const map_iterator<K, V, F, C> &,
const map_iterator<K, V, F, C> &);
public:
map_iterator();
map_iterator(const map_iterator &);
/*map_iterator &operator =(const map_iterator &);
const map_iterator &operator =(const map_iterator &) const;*/
inline const map_iterator &operator ++() const;
inline const map_iterator &operator --() const;
inline map_iterator &operator ++();
inline map_iterator &operator --();
inline const map_iterator operator ++(int) const;
inline const map_iterator operator --(int) const;
inline map_iterator operator ++(int);
inline map_iterator operator --(int);
inline pair<const K, V> *operator ->();
inline const pair<const K, V> *operator ->() const;
inline const K &operator *() const;
private:
map_iterator(map_node<K, V, F, C> *);
private:
mutable map_node<K, V, F, C> *current;
};
template <class K, class V, class F, class C>
map_iterator<K, V, F, C>::map_iterator(map_node<K, V, F, C> *node)
:current(node)
{
}
template <class K, class V, class F, class C>
map_iterator<K, V, F, C>::map_iterator(const map_iterator<K, V, F, C> &s)
:current(s.current)
{
}
/*template <class K, class V, class F, class C>
map_iterator<K, V, F, C> &
map_iterator<K, V, F, C>::operator =(const map_iterator &s)
{
current = s.current;
return *this;
}
template <class K, class V, class F, class C>
const map_iterator<K, V, F, C> &
map_iterator<K, V, F, C>::operator =(const map_iterator &s) const
{
current = s.current;
return *this;
}*/
template <class K, class V, class F, class C>
map_iterator<K, V, F, C>::map_iterator()
:current(0)
{
}
template <class K, class V, class F, class C>
inline map_iterator<K, V, F, C> &
map_iterator<K, V, F, C>::operator ++()
{
current = current->list_next;
return *this;
}
template <class K, class V, class F, class C>
inline map_iterator<K, V, F, C> &
map_iterator<K, V, F, C>::operator --()
{
current = current->list_prev;
return *this;
}
template <class K, class V, class F, class C>
inline const map_iterator<K, V, F, C> &
map_iterator<K, V, F, C>::operator ++() const
{
current = current->list_next;
return *this;
}
template <class K, class V, class F, class C>
inline const map_iterator<K, V, F, C> &
map_iterator<K, V, F, C>::operator --() const
{
current = current->list_prev;
return *this;
}
template <class K, class V, class F, class C>
inline map_iterator<K, V, F, C>
map_iterator<K, V, F, C>::operator ++(int)
{
map_iterator<K, V, F, C> tmp(*this);
current = current->list_next;
return tmp;
}
template <class K, class V, class F, class C>
inline map_iterator<K, V, F, C>
map_iterator<K, V, F, C>::operator --(int)
{
map_iterator<K, V, F, C> tmp(*this);
current = current->list_prev;
return tmp;
}
template <class K, class V, class F, class C>
inline const map_iterator<K, V, F, C>
map_iterator<K, V, F, C>::operator ++(int) const
{
map_iterator<K, V, F, C> tmp(*this);
current = current->list_next;
return tmp;
}
template <class K, class V, class F, class C>
inline const map_iterator<K, V, F, C>
map_iterator<K, V, F, C>::operator --(int) const
{
map_iterator<K, V, F, C> tmp(*this);
current = current->list_prev;
return tmp;
}
template <class K, class V, class F, class C>
inline pair<const K, V> *
map_iterator<K, V, F, C>::operator ->()
{
return ¤t->key_value;
}
template <class K, class V, class F, class C>
inline const pair<const K, V> *
map_iterator<K, V, F, C>::operator ->() const
{
return ¤t->key_value;
}
template <class K, class V, class F, class C>
inline const K &map_iterator<K, V, F, C>::operator *() const
{
return current->key_value.first;
}
template <class K, class V, class F, class C>
inline static bool operator ==(
const map_iterator<K, V, F, C> &a,
const map_iterator<K, V, F, C> &b)
{
return a.current == b.current;
}
template <class K, class V, class F, class C>
inline static bool operator !=(
const map_iterator<K, V, F, C> &a,
const map_iterator<K, V, F, C> &b)
{
return a.current != b.current;
}
template <class K, class V, class F,
class C = std::equal_to<K> >
class hash_map {
public:
typedef map_iterator<K, V, F, C> iterator;
typedef const map_iterator<K, V, F, C> const_iterator;
public:
hash_map();
explicit hash_map(size_t);
~hash_map();
public:
inline size_t size() const;
inline const_iterator begin() const;
inline const_iterator end() const;
inline iterator begin();
inline iterator end();
pair<map_iterator<K, V, F, C>, bool>
insert(const pair<K, V> &);
inline map_iterator<K, V, F, C> find(const K &) const;
void erase(const map_iterator<K, V, F, C> &);
inline void clear();
private:
hash_map(const hash_map &);
hash_map &operator =(const hash_map &);
private:
void destroy_slot(map_node<K, V, F, C> *);
map_iterator<K, V, F, C>
find_slot(map_node<K, V, F, C> *, const K &) const;
void insert_hash(map_node<K, V, F, C> *, size_t);
void insert_list(map_node<K, V, F, C> *);
void erase_hash(map_node<K, V, F, C> *);
void erase_list(map_node<K, V, F, C> *);
private:
map_node<K, V, F, C> **hash_slot;
map_node<K, V, F, C> *hash_list;
size_t slot_count;
size_t elmt_count;
};
template <class K, class V, class F, class C>
hash_map<K, V, F, C>::hash_map()
:hash_list(0), slot_count(DEFAULT_HASH_SIZE),
elmt_count(0)
{
hash_slot = new map_node<K, V, F, C> *[DEFAULT_HASH_SIZE];
assert(hash_slot);
memset(hash_slot, 0, sizeof(void *) * DEFAULT_HASH_SIZE);
}
template <class K, class V, class F, class C>
hash_map<K, V, F, C>::hash_map(size_t hs)
:hash_list(0), slot_count(hs),
elmt_count(0)
{
hash_slot = new map_node<K, V, F, C> *[hs];
assert(hash_slot);
memset(hash_slot, 0, sizeof(void *) * hs);
}
template <class K, class V, class F, class C>
hash_map<K, V, F, C>::~hash_map()
{
destroy_slot(hash_list);
delete [] hash_slot;
}
template <class K, class V, class F, class C>
void hash_map<K, V, F, C>::destroy_slot(map_node<K, V, F, C> *node)
{
while(node) {
map_node<K, V, F, C> *tmp = node;
node = node->list_next;
delete tmp;
}
}
template <class K, class V, class F, class C>
inline size_t hash_map<K, V, F, C>::size() const
{
return elmt_count;
}
template <class K, class V, class F, class C>
inline map_iterator<K, V, F, C>
hash_map<K, V, F, C>::find(const K &k) const
{
F fun;
size_t p = fun(k) % slot_count;
return find_slot(hash_slot[p], k);
}
template <class K, class V, class F, class C>
map_iterator<K, V, F, C>
hash_map<K, V, F, C>::find_slot(
map_node<K, V, F, C> *node, const K &k) const
{
C cmp;
while(node) {
if(cmp(node->key_value.first, k))
return map_iterator<K, V, F, C>(node);
node = node->slot_next;
}
return map_iterator<K, V, F, C>(0);
}
template <class K, class V, class F, class C>
pair<map_iterator<K, V, F, C>, bool>
hash_map<K, V, F, C>::insert(const pair<K, V> &kv)
{
F fun;
size_t p = fun(kv.first) % slot_count;
map_iterator<K, V, F, C> pos =
find_slot(hash_slot[p], kv.first);
bool ss = false;
if(pos == map_iterator<K, V, F, C>(0)) {
map_node<K, V, F, C> *node =
new map_node<K, V, F, C>(kv);
insert_hash(node, p);
insert_list(node);
ss = true;
++elmt_count;
}
return std::make_pair(pos, ss);
}
template <class K, class V, class F, class C>
void hash_map<K, V, F, C>::insert_hash(map_node<K, V, F, C> *node,
size_t p)
{
//node->slot_next = hash_slot[p];
if(hash_slot[p]) {
node->slot_next = hash_slot[p];
hash_slot[p]->slot_prev = node;
}
hash_slot[p] = node;
}
template <class K, class V, class F, class C>
void hash_map<K, V, F, C>::insert_list(map_node<K, V, F, C> *node)
{
//node->list_next = hash_list;
if(hash_list) {
node->list_next = hash_list;
hash_list->list_prev = node;
}
hash_list = node;
}
template <class K, class V, class F, class C>
void hash_map<K, V, F, C>::erase(const map_iterator<K, V, F, C> &pos)
{
map_node<K, V, F, C> *node = pos.current;
erase_hash(node);
erase_list(node);
delete node;
--elmt_count;
}
template <class K, class V, class F, class C>
void hash_map<K, V, F, C>::erase_hash(map_node<K, V, F, C> *node)
{
if(node->slot_next)
node->slot_next->slot_prev = node->slot_prev;
if(node->slot_prev) {
node->slot_prev->slot_next = node->slot_next;
} else {
F fun;
size_t p = fun(node->key_value.first) % slot_count;
hash_slot[p] = node->slot_next;
}
}
template <class K, class V, class F, class C>
void hash_map<K, V, F, C>::erase_list(map_node<K, V, F, C> *node)
{
if(node->list_next)
node->list_next->list_prev = node->list_prev;
if(node->list_prev)
node->list_prev->list_next = node->list_next;
else
hash_list = node->list_next;
}
template <class K, class V, class F, class C>
inline map_iterator<K, V, F, C>
hash_map<K, V, F, C>::begin()
{
return iterator(hash_list);
}
template <class K, class V, class F, class C>
inline map_iterator<K, V, F, C>
hash_map<K, V, F, C>::end()
{
return iterator(0);
}
template <class K, class V, class F, class C>
inline const map_iterator<K, V, F, C>
hash_map<K, V, F, C>::begin() const
{
return iterator(hash_list);
}
template <class K, class V, class F, class C>
inline const map_iterator<K, V, F, C>
hash_map<K, V, F, C>::end() const
{
return iterator(0);
}
template <class K, class V, class F, class C>
inline void hash_map<K, V, F, C>::clear()
{
destroy_slot(hash_list);
elmt_count = 0;
hash_list = 0;
memset(hash_slot, 0, sizeof(void *) * slot_count);
}
//==================hash_set===============
// template: Key, hash Function, Compare
template <class K, class F,
class C = std::equal_to<K> >
class hash_set : public hash_map<K, char, F, C> {
public:
typedef map_iterator<K, char, F, C> iterator;
typedef const map_iterator<K, char, F, C> const_iterator;
public:
hash_set();
explicit hash_set(size_t);
public:
pair<map_iterator<K, char, F, C>, bool>
insert(const K &);
private:
hash_set(const hash_set &);
hash_set &operator =(const hash_set &);
};
template <class K, class F, class C>
hash_set<K, F, C>::hash_set()
:hash_map<K, char, F, C>::hash_map()
{
}
template <class K, class F, class C>
hash_set<K, F, C>::hash_set(size_t s)
:hash_map<K, char, F, C>::hash_map(s)
{
}
template <class K, class F, class C>
pair<map_iterator<K, char, F, C>, bool>
hash_set<K, F, C>::insert(const K &k)
{
return hash_map<K, char, F, C>::insert(std::make_pair(k, 0));
}
} // end of namespace
#endif
=============================================
她们的使用方法与stl中的容器类相似,支持插入,查找,删除,遍历等。
成员函数名称和语义基本与stl中的容器类一致。
迭代器的使用也与stl容器类的基本一致。
main.cpp中的代码是个简单的测试用例,我写的有点乱。
编译:g++ -g -W -Wall -Wextra -o mytest main.cpp
执行:./mytest
main.cpp:
==============================================
// 2012年 02月 13日 星期一 14:15:42 CST
// author: 李小丹(Li Shao Dan) 字 殊恒(shuheng)
// K.I.S.S
// S.P.O.T
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <unistd.h>
#include "shuheng_hash.h"
using namespace std;
void tst_hash();
void tst_hash1();
class hash {
public:
inline size_t operator ()(int k)
{
return k;
}
};
int main()
{
tst_hash();
tst_hash1();
return 0;
}
void tst_hash()
{
shuheng::hash_map<int, int, hash> myhash(7);
for(int i = 0; i < 65; ++i)
myhash.insert(make_pair(i, i));
cout << myhash.size() << endl;
sleep(1);
for(shuheng::hash_map<int, int, hash>::const_iterator p
= myhash.begin(); p != myhash.end(); ++p)
cout << p->first << "\t" << p->second << endl;
cout << "====================================\n";
sleep(1);
for(shuheng::hash_map<int, int, hash>::iterator p
= myhash.begin(); p != myhash.end(); ++p)
p->second *= 2;
for(shuheng::hash_map<int, int, hash>::const_iterator p
= myhash.begin(); p != myhash.end(); ++p)
cout << p->first << "\t" << p->second << endl;
cout << "====================================\n";
sleep(1);
shuheng::hash_map<int, int, hash>::iterator pos;
if((pos = myhash.find(38)) != myhash.end())
myhash.erase(pos);
for(shuheng::hash_map<int, int, hash>::const_iterator p
= myhash.begin(); p != myhash.end(); ++p)
cout << p->first << "\t" << p->second << endl;
cout << "====================================\n";
cout << myhash.size() << endl;
sleep(1);
for(shuheng::hash_map<int, int, hash>::iterator p
= myhash.begin(); p != myhash.end(); ++p)
myhash.erase(p);
cout << myhash.size() << endl;
for(int i = 0; i < 88; ++i)
myhash.insert(make_pair(i, i * 3));
for(shuheng::hash_map<int, int, hash>::const_iterator p
= myhash.begin(); p != myhash.end(); ++p)
cout << p->first << "\t" << p->second << endl;
cout << "====================================\n";
sleep(1);
myhash.clear();
shuheng::hash_map<int, int, hash> myhash1;
for(int i = 0; i < 17; ++i)
myhash1.insert(make_pair(i, i));
shuheng::hash_map<int, int, hash>::iterator p;
int i = 0;
for(p = myhash1.begin(); i < 16; ++p, ++i)
cout << p->first << "\t" << p->second << endl;
cout << "====================================\n";
sleep(1);
for(shuheng::hash_map<int, int, hash>::const_iterator pos = p; pos != myhash1.end(); --pos)
cout << pos->first << "\t" << pos->second << endl;
cout << "====================================\n";
sleep(1);
for(shuheng::hash_map<int, int, hash>::const_iterator p
= myhash1.begin(); p != myhash1.end(); p++)
cout << p->first << "\t" << p->second << endl;
cout << "====================================\n";
sleep(1);
i = 0;
for(p = myhash1.begin(); i < 16; p++, ++i)
cout << p->first << "\t" << p->second << endl;
cout << "====================================\n";
sleep(1);
for(shuheng::hash_map<int, int, hash>::const_iterator pos = p; pos != myhash1.end(); pos--)
cout << pos->first << "\t" << pos->second << endl;
cout << "====================================\n";
sleep(1);
if((p = myhash1.find(3)) != myhash1.end()) {
myhash1.erase(p++);
myhash1.erase(p--);
}
for(shuheng::hash_map<int, int, hash>::const_iterator pos = myhash1.begin(); pos != myhash1.end(); ++pos)
cout << pos->first << "\t" << pos->second << endl;
cout << "====================================\n";
}
class hash_fun {
public:
size_t operator ()(char *buf) const
{
size_t h = 0;
unsigned char *p = (unsigned char *)buf;
for(int i = 0; *p; ++i, ++p)
h += *p * 37 * i;
return h;
}
};
class hash_cmp {
public:
bool operator ()(const char *p1, const char *p2) const
{
return strcmp(p1, p2) == 0;
}
};
void tst_hash1()
{
shuheng::hash_set<char *, hash_fun, hash_cmp> myhash;
FILE *fp;
if((fp = fopen("./main.cpp", "r"))) {
char buf[2048];
while(fgets(buf, sizeof(buf), fp)) {
int len = strlen(buf);
if(len < 2) continue;
char *p = new char [len];
strncpy(p, buf, len - 1);
p[len-1] = 0;
pair<shuheng::hash_set<char *, hash_fun,
hash_cmp>::iterator, bool> ret
= myhash.insert(p);
if(!ret.second)
delete [] p;
}
fclose(fp);
}
for(shuheng::hash_set<char *, hash_fun, hash_cmp>::iterator p
= myhash.begin(); p != myhash.end();
++p)
cout << *p << endl;
if((fp = fopen("./main.cpp", "r"))) {
char buf[2048];
while(fgets(buf, sizeof(buf), fp)) {
int len = strlen(buf);
if(len < 2) continue;
buf[len-1] = 0;
shuheng::hash_set<char *,
hash_fun, hash_cmp>::iterator p;
if((p = myhash.find(buf)) == myhash.end())
cout << "can't find!" << endl;
}
fclose(fp);
}
for(shuheng::hash_set<char *, hash_fun, hash_cmp>::iterator p
= myhash.begin(); p != myhash.end();
++p)
delete [] *p;
myhash.clear();
}
=============================================
shuheng_hash.h:
=============================================
// 2012年 02月 09日 星期四 08:49:48 CST
// author: 李小丹(Li Shao Dan) 字 殊恒(shuheng)
// K.I.S.S
// S.P.O.T
#ifndef SHUHENG_HASH_H
#define SHUHENG_HASH_H
#include <utility>
#include <functional>
#include <cstring>
#include <cassert>
using std::pair;
#define DEFAULT_HASH_SIZE 1021
namespace shuheng {
//==================hash_map=====================
//template: Key, Value, hash Function, Compare
template <class K, class V, class F, class C>
class hash_map;
template <class K, class V, class F, class C>
class map_iterator;
template <class K, class V, class F, class C>
inline static bool operator ==(
const map_iterator<K, V, F, C> &,
const map_iterator<K, V, F, C> &);
template <class K, class V, class F, class C>
inline static bool operator !=(
const map_iterator<K, V, F, C> &,
const map_iterator<K, V, F, C> &);
template <class K, class V, class F, class C>
class map_node {
public:
friend class hash_map<K, V, F, C>;
friend class map_iterator<K, V, F, C>;
private:
map_node(const pair<K, V> &);
private:
pair<const K, V> key_value;
map_node *slot_next;
map_node *slot_prev;
map_node *list_next;
map_node *list_prev;
};
template <class K, class V, class F, class C>
map_node<K, V, F, C>::map_node(const pair<K, V> &kv)
:key_value(kv), slot_next(0),
slot_prev(0), list_next(0), list_prev(0)
{
}
template <class K, class V, class F, class C>
class map_iterator {
public:
friend class hash_map<K, V, F, C>;
friend bool operator ==<K, V, F, C>(
const map_iterator<K, V, F, C> &,
const map_iterator<K, V, F, C> &);
friend bool operator !=<K, V, F, C>(
const map_iterator<K, V, F, C> &,
const map_iterator<K, V, F, C> &);
public:
map_iterator();
map_iterator(const map_iterator &);
/*map_iterator &operator =(const map_iterator &);
const map_iterator &operator =(const map_iterator &) const;*/
inline const map_iterator &operator ++() const;
inline const map_iterator &operator --() const;
inline map_iterator &operator ++();
inline map_iterator &operator --();
inline const map_iterator operator ++(int) const;
inline const map_iterator operator --(int) const;
inline map_iterator operator ++(int);
inline map_iterator operator --(int);
inline pair<const K, V> *operator ->();
inline const pair<const K, V> *operator ->() const;
inline const K &operator *() const;
private:
map_iterator(map_node<K, V, F, C> *);
private:
mutable map_node<K, V, F, C> *current;
};
template <class K, class V, class F, class C>
map_iterator<K, V, F, C>::map_iterator(map_node<K, V, F, C> *node)
:current(node)
{
}
template <class K, class V, class F, class C>
map_iterator<K, V, F, C>::map_iterator(const map_iterator<K, V, F, C> &s)
:current(s.current)
{
}
/*template <class K, class V, class F, class C>
map_iterator<K, V, F, C> &
map_iterator<K, V, F, C>::operator =(const map_iterator &s)
{
current = s.current;
return *this;
}
template <class K, class V, class F, class C>
const map_iterator<K, V, F, C> &
map_iterator<K, V, F, C>::operator =(const map_iterator &s) const
{
current = s.current;
return *this;
}*/
template <class K, class V, class F, class C>
map_iterator<K, V, F, C>::map_iterator()
:current(0)
{
}
template <class K, class V, class F, class C>
inline map_iterator<K, V, F, C> &
map_iterator<K, V, F, C>::operator ++()
{
current = current->list_next;
return *this;
}
template <class K, class V, class F, class C>
inline map_iterator<K, V, F, C> &
map_iterator<K, V, F, C>::operator --()
{
current = current->list_prev;
return *this;
}
template <class K, class V, class F, class C>
inline const map_iterator<K, V, F, C> &
map_iterator<K, V, F, C>::operator ++() const
{
current = current->list_next;
return *this;
}
template <class K, class V, class F, class C>
inline const map_iterator<K, V, F, C> &
map_iterator<K, V, F, C>::operator --() const
{
current = current->list_prev;
return *this;
}
template <class K, class V, class F, class C>
inline map_iterator<K, V, F, C>
map_iterator<K, V, F, C>::operator ++(int)
{
map_iterator<K, V, F, C> tmp(*this);
current = current->list_next;
return tmp;
}
template <class K, class V, class F, class C>
inline map_iterator<K, V, F, C>
map_iterator<K, V, F, C>::operator --(int)
{
map_iterator<K, V, F, C> tmp(*this);
current = current->list_prev;
return tmp;
}
template <class K, class V, class F, class C>
inline const map_iterator<K, V, F, C>
map_iterator<K, V, F, C>::operator ++(int) const
{
map_iterator<K, V, F, C> tmp(*this);
current = current->list_next;
return tmp;
}
template <class K, class V, class F, class C>
inline const map_iterator<K, V, F, C>
map_iterator<K, V, F, C>::operator --(int) const
{
map_iterator<K, V, F, C> tmp(*this);
current = current->list_prev;
return tmp;
}
template <class K, class V, class F, class C>
inline pair<const K, V> *
map_iterator<K, V, F, C>::operator ->()
{
return ¤t->key_value;
}
template <class K, class V, class F, class C>
inline const pair<const K, V> *
map_iterator<K, V, F, C>::operator ->() const
{
return ¤t->key_value;
}
template <class K, class V, class F, class C>
inline const K &map_iterator<K, V, F, C>::operator *() const
{
return current->key_value.first;
}
template <class K, class V, class F, class C>
inline static bool operator ==(
const map_iterator<K, V, F, C> &a,
const map_iterator<K, V, F, C> &b)
{
return a.current == b.current;
}
template <class K, class V, class F, class C>
inline static bool operator !=(
const map_iterator<K, V, F, C> &a,
const map_iterator<K, V, F, C> &b)
{
return a.current != b.current;
}
template <class K, class V, class F,
class C = std::equal_to<K> >
class hash_map {
public:
typedef map_iterator<K, V, F, C> iterator;
typedef const map_iterator<K, V, F, C> const_iterator;
public:
hash_map();
explicit hash_map(size_t);
~hash_map();
public:
inline size_t size() const;
inline const_iterator begin() const;
inline const_iterator end() const;
inline iterator begin();
inline iterator end();
pair<map_iterator<K, V, F, C>, bool>
insert(const pair<K, V> &);
inline map_iterator<K, V, F, C> find(const K &) const;
void erase(const map_iterator<K, V, F, C> &);
inline void clear();
private:
hash_map(const hash_map &);
hash_map &operator =(const hash_map &);
private:
void destroy_slot(map_node<K, V, F, C> *);
map_iterator<K, V, F, C>
find_slot(map_node<K, V, F, C> *, const K &) const;
void insert_hash(map_node<K, V, F, C> *, size_t);
void insert_list(map_node<K, V, F, C> *);
void erase_hash(map_node<K, V, F, C> *);
void erase_list(map_node<K, V, F, C> *);
private:
map_node<K, V, F, C> **hash_slot;
map_node<K, V, F, C> *hash_list;
size_t slot_count;
size_t elmt_count;
};
template <class K, class V, class F, class C>
hash_map<K, V, F, C>::hash_map()
:hash_list(0), slot_count(DEFAULT_HASH_SIZE),
elmt_count(0)
{
hash_slot = new map_node<K, V, F, C> *[DEFAULT_HASH_SIZE];
assert(hash_slot);
memset(hash_slot, 0, sizeof(void *) * DEFAULT_HASH_SIZE);
}
template <class K, class V, class F, class C>
hash_map<K, V, F, C>::hash_map(size_t hs)
:hash_list(0), slot_count(hs),
elmt_count(0)
{
hash_slot = new map_node<K, V, F, C> *[hs];
assert(hash_slot);
memset(hash_slot, 0, sizeof(void *) * hs);
}
template <class K, class V, class F, class C>
hash_map<K, V, F, C>::~hash_map()
{
destroy_slot(hash_list);
delete [] hash_slot;
}
template <class K, class V, class F, class C>
void hash_map<K, V, F, C>::destroy_slot(map_node<K, V, F, C> *node)
{
while(node) {
map_node<K, V, F, C> *tmp = node;
node = node->list_next;
delete tmp;
}
}
template <class K, class V, class F, class C>
inline size_t hash_map<K, V, F, C>::size() const
{
return elmt_count;
}
template <class K, class V, class F, class C>
inline map_iterator<K, V, F, C>
hash_map<K, V, F, C>::find(const K &k) const
{
F fun;
size_t p = fun(k) % slot_count;
return find_slot(hash_slot[p], k);
}
template <class K, class V, class F, class C>
map_iterator<K, V, F, C>
hash_map<K, V, F, C>::find_slot(
map_node<K, V, F, C> *node, const K &k) const
{
C cmp;
while(node) {
if(cmp(node->key_value.first, k))
return map_iterator<K, V, F, C>(node);
node = node->slot_next;
}
return map_iterator<K, V, F, C>(0);
}
template <class K, class V, class F, class C>
pair<map_iterator<K, V, F, C>, bool>
hash_map<K, V, F, C>::insert(const pair<K, V> &kv)
{
F fun;
size_t p = fun(kv.first) % slot_count;
map_iterator<K, V, F, C> pos =
find_slot(hash_slot[p], kv.first);
bool ss = false;
if(pos == map_iterator<K, V, F, C>(0)) {
map_node<K, V, F, C> *node =
new map_node<K, V, F, C>(kv);
insert_hash(node, p);
insert_list(node);
ss = true;
++elmt_count;
}
return std::make_pair(pos, ss);
}
template <class K, class V, class F, class C>
void hash_map<K, V, F, C>::insert_hash(map_node<K, V, F, C> *node,
size_t p)
{
//node->slot_next = hash_slot[p];
if(hash_slot[p]) {
node->slot_next = hash_slot[p];
hash_slot[p]->slot_prev = node;
}
hash_slot[p] = node;
}
template <class K, class V, class F, class C>
void hash_map<K, V, F, C>::insert_list(map_node<K, V, F, C> *node)
{
//node->list_next = hash_list;
if(hash_list) {
node->list_next = hash_list;
hash_list->list_prev = node;
}
hash_list = node;
}
template <class K, class V, class F, class C>
void hash_map<K, V, F, C>::erase(const map_iterator<K, V, F, C> &pos)
{
map_node<K, V, F, C> *node = pos.current;
erase_hash(node);
erase_list(node);
delete node;
--elmt_count;
}
template <class K, class V, class F, class C>
void hash_map<K, V, F, C>::erase_hash(map_node<K, V, F, C> *node)
{
if(node->slot_next)
node->slot_next->slot_prev = node->slot_prev;
if(node->slot_prev) {
node->slot_prev->slot_next = node->slot_next;
} else {
F fun;
size_t p = fun(node->key_value.first) % slot_count;
hash_slot[p] = node->slot_next;
}
}
template <class K, class V, class F, class C>
void hash_map<K, V, F, C>::erase_list(map_node<K, V, F, C> *node)
{
if(node->list_next)
node->list_next->list_prev = node->list_prev;
if(node->list_prev)
node->list_prev->list_next = node->list_next;
else
hash_list = node->list_next;
}
template <class K, class V, class F, class C>
inline map_iterator<K, V, F, C>
hash_map<K, V, F, C>::begin()
{
return iterator(hash_list);
}
template <class K, class V, class F, class C>
inline map_iterator<K, V, F, C>
hash_map<K, V, F, C>::end()
{
return iterator(0);
}
template <class K, class V, class F, class C>
inline const map_iterator<K, V, F, C>
hash_map<K, V, F, C>::begin() const
{
return iterator(hash_list);
}
template <class K, class V, class F, class C>
inline const map_iterator<K, V, F, C>
hash_map<K, V, F, C>::end() const
{
return iterator(0);
}
template <class K, class V, class F, class C>
inline void hash_map<K, V, F, C>::clear()
{
destroy_slot(hash_list);
elmt_count = 0;
hash_list = 0;
memset(hash_slot, 0, sizeof(void *) * slot_count);
}
//==================hash_set===============
// template: Key, hash Function, Compare
template <class K, class F,
class C = std::equal_to<K> >
class hash_set : public hash_map<K, char, F, C> {
public:
typedef map_iterator<K, char, F, C> iterator;
typedef const map_iterator<K, char, F, C> const_iterator;
public:
hash_set();
explicit hash_set(size_t);
public:
pair<map_iterator<K, char, F, C>, bool>
insert(const K &);
private:
hash_set(const hash_set &);
hash_set &operator =(const hash_set &);
};
template <class K, class F, class C>
hash_set<K, F, C>::hash_set()
:hash_map<K, char, F, C>::hash_map()
{
}
template <class K, class F, class C>
hash_set<K, F, C>::hash_set(size_t s)
:hash_map<K, char, F, C>::hash_map(s)
{
}
template <class K, class F, class C>
pair<map_iterator<K, char, F, C>, bool>
hash_set<K, F, C>::insert(const K &k)
{
return hash_map<K, char, F, C>::insert(std::make_pair(k, 0));
}
} // end of namespace
#endif
=============================================