模仿stl,实现了开链法形式的hashtable。纯属练手,只实现其基本功能,不当之处还望指正。本文为实现独立的空间配置器。
- #include<iostream>
- #include<vector>
- #include<algorithm>
- using namespace std;
- template<class value>
- struct _hash_node{
- value val;
- _hash_node *next;
- ~_hash_node(){delete val;}
- };
- template<class value,class key,class HashFcn,class EqualKey>
- class _hashtable;
- template<class T1,class T2>
- class _hashfcn_mod;
- template<class value,class key,class HashFcn,class EqualKey>
- class _hashtable_iterator{
- public:
- typedef _hashtable<value,key,HashFcn,EqualKey> hashtable;
- typedef _hashtable_iterator<value,key,HashFcn,EqualKey> iterator;
- typedef _hash_node<value> node;
- typedef forward_iterator_tag iterator_category;
- typedef value value_type;
- typedef ptrdiff_t difference_type;
- typedef size_t size_type;
- typedef value& reference;
- typedef value* pointer;
- node* cur;
- hashtable* ht;
- iterator(node* n,hashtable* tab):cur(n),ht(tab){}
- iterator(){}
- reference operator*()const{return cur->val;}
- pointer operator->()const{return &(operator*()); }
- iterator& operator++(){
- const node* old = cur;
- cur = cur->next; //需要判断cur的next是否存在
- if(!cur){ //若此bucket list已经遍历到null 则继续向下一个bucket移动
- size_type bucket = ht->bkt_num(old->val);
- while(!cur&& ++bucket < ht->buckets.size())
- cur = ht->buckets[bucket];
- }
- return *this;
- }
- iterator operator++(int){
- const iterator old = cur;
- ++*this;
- return old;
- }
- bool operator==(const iterator& it)const{return cur == it.cur;}
- bool operator!=(const iterator& it)const{return cur != it.cur;}
- };
- static const int _stl_num_primes = 28; //保存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, 3221225473ul, 4294967291ul
- };
- //获取大于等于n的第一个质数
- inline unsigned long _stl_next_prime(unsigned long n){
- const unsigned long* first = _stl_prime_list;
- const unsigned long* last = _stl_prime_list + _stl_num_primes;
- const unsigned long* pos = lower_bound(first,last,n);
- return pos == last? *(last-1):*pos;
- }
- template<class value,class key,class HashFcn,class EqualKey>
- class _hashtable{
- public:
- typedef HashFcn hasher;
- typedef EqualKey key_equal;
- typedef value value_type;
- typedef key key_type;
- typedef value_type& reference;
- typedef size_t size_type;
- typedef _hash_node<value> node;
- typedef _hashtable_iterator<value,key,HashFcn,EqualKey> iterator;
- vector<node*> buckets;
- private:
- hasher hash; //哈希映射函数
- key_equal equals;
- size_type num_elements;
- private:
- void initialize_buckets(size_type n){
- const size_type n_buckets = next_size(n);
- buckets.reserve(n_buckets);
- buckets.insert(buckets.end(), n_buckets, (node*) 0);
- num_elements = 0;
- }
- size_type next_size(size_type n)const{return _stl_next_prime(n);}
- void copy_from(const _hashtable& ht) {
- buckets.clear();
- buckets.reserve(ht.buckets.size());
- buckets.insert(buckets.end(), ht.buckets.size(), (node*) 0);
- try {
- for (size_type i = 0; i < ht.buckets.size(); ++i) {
- if (const node* cur = ht.buckets[i]) {
- node* copy = new_node(cur->val);
- buckets[i] = copy;
- for (node* next = cur->next; next; cur = next, next = cur->next) {
- copy->next = new_node(next->val);
- copy = copy->next;
- }
- }
- }
- num_elements = ht.num_elements;
- }
- catch(...){
- clear();
- }
- }
- node* new_node(const value_type& obj)
- {
- node* n = allocate((node*)0);
- n->next = 0;
- try {
- construct(&n->val, obj);
- return n;
- }
- catch(...){
- deallocate(n);
- exit(1);
- }
- }
- template<class T>
- T* allocate(T* a,ptrdiff_t size=1){
- set_new_handler(0);
- T* tmp = (T*)(::operator new((size_t)(size*sizeof(T))));
- if(tmp == 0){
- cerr<<"out of memory."<<endl;
- exit(1);
- }
- return tmp;
- }
- template<class T1,class T2>
- void construct(T1* p,const T2& value){new (p)T1(value);}
- template<class T>
- void deallocate(T* buffer){::operator delete(buffer);}
- void clear(){
- for (size_type i = 0; i < buckets.size(); ++i) {
- node* cur = buckets[i];
- while (cur != 0) {
- node* next = cur->next;
- delete_node(cur);
- cur = next;
- }
- buckets[i] = 0;
- }
- num_elements = 0;
- }
- void delete_node(node* n)
- {
- destroy(&n->val);
- deallocate(n);
- }
- template <class T>
- void destroy(T* pointer) {
- pointer->~T();
- }
- size_type bkt_num_key(const key_type& key)
- {
- return bkt_num_key(key, buckets.size());
- }
- size_type bkt_num_key(const key_type& key, size_t n)
- {
- return hash(key,n);// % n;
- }
- iterator insert_equal_noresize(const value_type& obj){
- size_type n = bkt_num(obj);
- node* first = buckets[n];
- for(node* cur=first;cur;cur=cur->next){
- if(equals(get_key(cur->val),get_key(obj))){
- node* tmp = new_node(obj);
- tmp->next = cur->next;
- cur->next = tmp;
- ++num_elements;
- returniterator(tmp,this);
- }
- }
- node* tmp = new_node(obj);
- tmp->next = first;
- buckets[n] = tmp;
- return iterator(tmp,this);
- }
- pair<iterator, bool> insert_unique_noresize(const value_type& obj){
- const size_type n = bkt_num(obj);
- node* first = buckets[n];
- for (node* cur = first; cur; cur = cur->next)
- if (equals(get_key(cur->val), get_key(obj)))
- return pair<iterator, bool>(iterator(cur, this), false);
- node* tmp = new_node(obj);
- tmp->next = first;
- buckets[n] = tmp;
- ++num_elements;
- return pair<iterator, bool>(iterator(tmp, this), true);
- }
- value_type get_key(const value_type& obj){
- ExtractKey<value_type> tmp;
- return tmp(obj);
- }
- public:
- size_type bucket_size(){return buckets.size();}
- _hashtable(size_type n,const HashFcn& hf,const EqualKey& eql):hash(hf),equals(eql){
- initialize_buckets(n);
- }
- _hashtable(const _hashtable& ht):hash(ht.hash),equals(ht.equals),num_elements(0){
- copy_from(ht);
- }
- _hashtable(){clear();}
- size_type bucket_count()const{return buckets.size();}
- size_type max_bucket_count()const{return _stl_prime_list[_stl_num_primes - 1];}
- size_type elems_in_bucket(size_type bucket)const{
- size_type result = 0;
- for(*node cur = buckets[bucket];cur;cur = cur->next)
- result += 1;
- return result;
- }
- size_type bkt_num(const value_type& obj)
- {
- return bkt_num_key(get_key(obj));
- }
- size_type bkt_num(const value_type& obj, size_t n) const
- {
- return bkt_num_key(get_key(obj), n);
- }
- void resize(size_type num_elements_hint){
- _hashfcn_mod<value_type,value_type> hashfcn_mod;
- const size_type old_n = buckets.size();
- if(num_elements_hint > old_n){
- const size_type n = next_size(num_elements_hint);
- if(n > old_n){
- vector<node*> tmp(n,(node*)0);
- try{
- for(size_type bucket=0;bucket<old_n;++bucket){
- node* first = buckets[bucket];
- while(first){
- size_type new_bucket = hashfcn_mod(first->val,n);
- buckets[bucket] = first->next;
- first->next = tmp[new_bucket];
- tmp[new_bucket] = first;
- first = buckets[bucket];
- }
- }
- buckets.swap(tmp);
- }
- catch(...){
- for(size_type bucket=0;bucket<tmp.size();++bucket){
- while(tmp[bucket]){
- node* next = tmp[bucket]->next;
- delete_node(tmp[bucket]);
- tmp[bucket] = next;
- }
- }
- throw;
- }
- }
- }
- }
- pair<iterator,bool> insert_unique(const value_type& obj){
- resize(num_elements+1);
- return insert_unique_noresize(obj);
- }
- iterator insert_equal(const value_type& obj)
- {
- resize(num_elements + 1);
- return insert_equal_noresize(obj);
- }
- iterator begin()
- {
- for (size_type n = 0; n < buckets.size(); ++n)
- if (buckets[n])
- return iterator(buckets[n], this);
- return end();
- }
- iterator end() { return iterator(0, this); }
- size_type erase(const key_type& key)
- {
- const size_type n = bkt_num_key(key);
- node* first = buckets[n];
- size_type erased = 0;
- if (first) {
- node* cur = first;
- node* next = cur->next;
- while (next) {
- if (equals(get_key(next->val), key)) {
- cur->next = next->next;
- delete_node(next);
- next = cur->next;
- ++erased;
- --num_elements;
- }
- else {
- cur = next;
- next = cur->next;
- }
- }
- if (equals(get_key(first->val), key)) {
- buckets[n] = first->next;
- delete_node(first);
- ++erased;
- --num_elements;
- }
- }
- return erased;
- }
- void erase(const iterator& it)
- {
- if (node* const p = it.cur) {
- const size_type n = bkt_num(p->val);
- node* cur = buckets[n];
- if (cur == p) {
- buckets[n] = cur->next;
- delete_node(cur);
- --num_elements;
- }
- else {
- node* next = cur->next;
- while (next) {
- if (next == p) {
- cur->next = next->next;
- delete_node(next);
- --num_elements;
- break;
- }
- else {
- cur = next;
- next = cur->next;
- }
- }
- }
- }
- }
- reference find_or_insert(const value_type& obj){
- resize(num_elements + 1);
- size_type n = bkt_num(obj);
- node* first = buckets[n];
- for (node* cur = first; cur; cur = cur->next)
- if (equals(get_key(cur->val), get_key(obj)))
- return cur->val;
- node* tmp = new_node(obj);
- tmp->next = first;
- buckets[n] = tmp;
- ++num_elements;
- return tmp->val;
- }
- iterator find(const key_type& key){
- size_type n = bkt_num_key(key);
- node* first;
- for ( first = buckets[n];first && !equals(get_key(first->val), key);
- first = first->next);
- return iterator(first, this);
- }
- void erase(iterator first, iterator last){
- size_type f_bucket = first.cur ? bkt_num(first.cur->val) : buckets.size();
- size_type l_bucket = last.cur ? bkt_num(last.cur->val) : buckets.size();
- if (first.cur == last.cur)return;
- else if (f_bucket == l_bucket)erase_bucket(f_bucket, first.cur, last.cur);
- else {
- erase_bucket(f_bucket, first.cur, 0);
- for (size_type n = f_bucket + 1; n < l_bucket; ++n)
- erase_bucket(n, 0);
- if (l_bucket != buckets.size())
- erase_bucket(l_bucket, last.cur);
- }
- }
- };
- /*****************************************************
- 此函数对象用于定义映射函数,根据自己的需求可以定义线性探测、
- 二次线性探测或者自定义函数
- ***********************************************************/
- template<class T1,class T2>
- class _hashfcn_mod{ //简单取余映射
- public:
- T1 operator()(T1 value,T2 size){ //value为key值 size为bucket长度
- return value % size;
- }
- };
- /*************************************************************
- 判断键值是否相等的函数,可自定义
- *************************************************************/
- template<class T>
- class _key_equal{
- public:
- bool operator()(T t1,T t2){
- return t1 == t2;
- }
- };
- /************************************************************
- 从节点中取出键值的方法,可自定义
- ***********************************************************/
- template<class T>
- class ExtractKey{ //从节点取出键值
- public:
- T operator()(const T& tmp){
- identity<T> id;
- return id(tmp);
- }
- };
- void test1(){
- _hashfcn_mod<int,int> hashfcn;
- _key_equal<int> keyequal;
- _hashtable<int,int,_hashfcn_mod<int,int>,_key_equal<int>> hashtab(20,hashfcn,keyequal);
- hashtab.insert_unique(15);
- hashtab.insert_unique(14);
- hashtab.insert_unique(13);
- hashtab.insert_unique(12);
- _hashtable<int,int,_hashfcn_mod<int,int>,_key_equal<int>>::iterator iter;
- for(iter = hashtab.begin();iter!= hashtab.end();++iter)
- cout<<*iter<<" ";
- cout<<endl;
- hashtab.erase(12);
- for(iter = hashtab.begin();iter!= hashtab.end();++iter)
- cout<<*iter<<" ";
- cout<<endl;
- hashtab.erase(hashtab.find(13));
- for(iter = hashtab.begin();iter!= hashtab.end();++iter)
- cout<<*iter<<" ";
- cout<<endl;
- }
- int main(){
- test1();
- }
http://www.qdxw.com.cn/yx/dwwf/3525622.html
http://www.qdxw.com.cn/yx/dwwf/3525623.html
http://www.qdxw.com.cn/yx/dwwf/3525628.html
http://www.qdxw.com.cn/yx/dwwf/3525657.html
http://www.qdxw.com.cn/yx/dwwf/3525661.html
http://www.qdxw.com.cn/yx/dwwf/3525672.html
http://www.qdxw.com.cn/yx/dwwf/3525660.html
http://www.qdxw.com.cn/yx/dwwf/3525686.html
http://www.qdxw.com.cn/yx/dwwf/3525674.html
http://www.qdxw.com.cn/yx/dwwf/3525694.html
http://www.qdxw.com.cn/yx/dwwf/3525683.html
http://www.zhoushan.cn/yy/mrdj/1636135.html
http://www.zhoushan.cn/yy/mrdj/1636110.html
http://www.zhoushan.cn/yy/mrdj/1636142.html
http://www.zhoushan.cn/yy/mrdj/1636127.html
http://www.zhoushan.cn/yy/mrdj/1636149.html
http://www.zhoushan.cn/yy/mrdj/1636149.html
http://www.zhoushan.cn/yy/mrdj/1636192.html
http://www.zhoushan.cn/yy/mrdj/1636208.html
http://www.zhoushan.cn/yy/mrdj/1636199.html
http://www.zhoushan.cn/yy/mrdj/1636227.html
http://www.tznews.cn/ys/ywzh/1181858.html
http://www.tznews.cn/ys/ywzh/1181857.html
http://www.tznews.cn/ys/ywzh/1181859.html
http://www.tznews.cn/ys/ywzh/1181871.html
http://www.tznews.cn/ys/ywzh/1181906.html
http://www.tznews.cn/ys/ywzh/1181915.html
http://www.tznews.cn/ys/ywzh/1181885.html
http://www.tznews.cn/ys/ywzh/1181899.html
http://www.tznews.cn/ys/ywzh/1181911.html
http://www.tznews.cn/ys/ywzh/1181902.html
http://www.changsha.cn/ys/zzys/4252294.html
http://www.changsha.cn/ys/zzys/4252214.html
http://www.changsha.cn/ys/zzys/4252396.html
http://www.changsha.cn/ys/zzys/4252459.html
http://www.changsha.cn/ys/zzys/4252456.html
http://www.changsha.cn/ys/zzys/4252508.html
http://www.changsha.cn/ys/zzys/4252702.html
http://www.changsha.cn/ys/zzys/4252729.html
http://www.changsha.cn/ys/zzys/4252741.html
http://www.changsha.cn/ys/zzys/4252771.html
http://www.changsha.cn/ys/csys/4252911.html
http://www.changsha.cn/ys/csys/4253240.html
http://www.changsha.cn/ys/csys/4253129.html
http://www.changsha.cn/ys/csys/4253161.html
http://www.changsha.cn/ys/csys/4253144.html
http://www.changsha.cn/ys/csys/4253140.html
http://www.changsha.cn/ys/csys/4253184.html
http://www.changsha.cn/ys/csys/4253308.html
http://www.changsha.cn/ys/csys/4253315.html
http://www.changsha.cn/ys/csys/4253289.html
http://www.js0573.com/yx/jsfs/6157297.html
http://www.js0573.com/yx/jsfs/6157325.html
http://www.js0573.com/yx/jsfs/6157707.html
http://www.js0573.com/yx/jsfs/6157595.html
http://www.js0573.com/yx/jsfs/6157635.html
http://www.js0573.com/yx/jsfs/6157590.html
http://www.js0573.com/yx/jsfs/6157639.html
http://www.js0573.com/yx/jsfs/6157656.html
http://www.js0573.com/yx/jsfs/6157915.html
http://www.qdxw.com.cn/yx/dwwf/3525623.html
http://www.qdxw.com.cn/yx/dwwf/3525628.html
http://www.qdxw.com.cn/yx/dwwf/3525657.html
http://www.qdxw.com.cn/yx/dwwf/3525661.html
http://www.qdxw.com.cn/yx/dwwf/3525672.html
http://www.qdxw.com.cn/yx/dwwf/3525660.html
http://www.qdxw.com.cn/yx/dwwf/3525686.html
http://www.qdxw.com.cn/yx/dwwf/3525674.html
http://www.qdxw.com.cn/yx/dwwf/3525694.html
http://www.qdxw.com.cn/yx/dwwf/3525683.html
http://www.zhoushan.cn/yy/mrdj/1636135.html
http://www.zhoushan.cn/yy/mrdj/1636110.html
http://www.zhoushan.cn/yy/mrdj/1636142.html
http://www.zhoushan.cn/yy/mrdj/1636127.html
http://www.zhoushan.cn/yy/mrdj/1636149.html
http://www.zhoushan.cn/yy/mrdj/1636149.html
http://www.zhoushan.cn/yy/mrdj/1636192.html
http://www.zhoushan.cn/yy/mrdj/1636208.html
http://www.zhoushan.cn/yy/mrdj/1636199.html
http://www.zhoushan.cn/yy/mrdj/1636227.html
http://www.tznews.cn/ys/ywzh/1181858.html
http://www.tznews.cn/ys/ywzh/1181857.html
http://www.tznews.cn/ys/ywzh/1181859.html
http://www.tznews.cn/ys/ywzh/1181871.html
http://www.tznews.cn/ys/ywzh/1181906.html
http://www.tznews.cn/ys/ywzh/1181915.html
http://www.tznews.cn/ys/ywzh/1181885.html
http://www.tznews.cn/ys/ywzh/1181899.html
http://www.tznews.cn/ys/ywzh/1181911.html
http://www.tznews.cn/ys/ywzh/1181902.html
http://www.changsha.cn/ys/zzys/4252294.html
http://www.changsha.cn/ys/zzys/4252214.html
http://www.changsha.cn/ys/zzys/4252396.html
http://www.changsha.cn/ys/zzys/4252459.html
http://www.changsha.cn/ys/zzys/4252456.html
http://www.changsha.cn/ys/zzys/4252508.html
http://www.changsha.cn/ys/zzys/4252702.html
http://www.changsha.cn/ys/zzys/4252729.html
http://www.changsha.cn/ys/zzys/4252741.html
http://www.changsha.cn/ys/zzys/4252771.html
http://www.changsha.cn/ys/csys/4252911.html
http://www.changsha.cn/ys/csys/4253240.html
http://www.changsha.cn/ys/csys/4253129.html
http://www.changsha.cn/ys/csys/4253161.html
http://www.changsha.cn/ys/csys/4253144.html
http://www.changsha.cn/ys/csys/4253140.html
http://www.changsha.cn/ys/csys/4253184.html
http://www.changsha.cn/ys/csys/4253308.html
http://www.changsha.cn/ys/csys/4253315.html
http://www.changsha.cn/ys/csys/4253289.html
http://www.js0573.com/yx/jsfs/6157297.html
http://www.js0573.com/yx/jsfs/6157325.html
http://www.js0573.com/yx/jsfs/6157707.html
http://www.js0573.com/yx/jsfs/6157595.html
http://www.js0573.com/yx/jsfs/6157635.html
http://www.js0573.com/yx/jsfs/6157590.html
http://www.js0573.com/yx/jsfs/6157639.html
http://www.js0573.com/yx/jsfs/6157656.html
http://www.js0573.com/yx/jsfs/6157915.html