hashtable C++实现

模仿stl,实现了开链法形式的hashtable。纯属练手,只实现其基本功能,不当之处还望指正。本文为实现独立的空间配置器。


[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #include<iostream>  
  2. #include<vector>  
  3. #include<algorithm>  
  4. using namespace std;  
  5. template<class value>  
  6. struct _hash_node{  
  7.     value val;  
  8.     _hash_node *next;  
  9.     ~_hash_node(){delete val;}  
  10. };  
  11. template<class value,class key,class HashFcn,class EqualKey>  
  12. class _hashtable;  
  13. template<class T1,class T2>  
  14. class _hashfcn_mod;  
  15. template<class value,class key,class HashFcn,class EqualKey>  
  16. class _hashtable_iterator{  
  17. public:  
  18.     typedef _hashtable<value,key,HashFcn,EqualKey> hashtable;  
  19.     typedef _hashtable_iterator<value,key,HashFcn,EqualKey> iterator;  
  20.     typedef _hash_node<value> node;  
  21.     typedef forward_iterator_tag iterator_category;  
  22.     typedef value value_type;  
  23.     typedef ptrdiff_t difference_type;  
  24.     typedef size_t size_type;  
  25.     typedef value& reference;  
  26.     typedef value* pointer;  
  27.     node* cur;  
  28.     hashtable* ht;  
  29.     iterator(node* n,hashtable* tab):cur(n),ht(tab){}  
  30.     iterator(){}  
  31.     reference operator*()const{return cur->val;}  
  32.     pointer operator->()const{return &(operator*()); }  
  33.     iterator& operator++(){  
  34.         const node* old = cur;  
  35.         cur = cur->next; //需要判断cur的next是否存在  
  36.         if(!cur){ //若此bucket list已经遍历到null 则继续向下一个bucket移动  
  37.             size_type bucket = ht->bkt_num(old->val);  
  38.             while(!cur&& ++bucket < ht->buckets.size())  
  39.                 cur = ht->buckets[bucket];  
  40.         }  
  41.         return *this;  
  42.     }  
  43.     iterator operator++(int){  
  44.         const iterator old = cur;  
  45.         ++*this;  
  46.         return old;  
  47.     }  
  48.     bool operator==(const iterator& it)const{return cur == it.cur;}  
  49.     bool operator!=(const iterator& it)const{return cur != it.cur;}  
  50. };  
  51. static const int _stl_num_primes = 28; //保存28个质数来设计表格大小  
  52. static const unsigned long _stl_prime_list[_stl_num_primes] = {  
  53.     53,         97,           193,         389,       769,    
  54.     1543,       3079,         6151,        12289,     24593,    
  55.     49157,      98317,        196613,      393241,    786433,    
  56.     1572869,    3145739,      6291469,     12582917,  25165843,    
  57.     50331653,   100663319,    201326611,   402653189, 805306457,    
  58.     1610612741, 3221225473ul, 4294967291ul   
  59. };  
  60.   
  61. //获取大于等于n的第一个质数  
  62. inline unsigned long _stl_next_prime(unsigned long n){  
  63.     const unsigned long* first = _stl_prime_list;  
  64.     const unsigned long* last = _stl_prime_list + _stl_num_primes;  
  65.     const unsigned long* pos = lower_bound(first,last,n);  
  66.     return pos == last? *(last-1):*pos;  
  67. }  
  68. template<class value,class key,class HashFcn,class EqualKey>  
  69. class _hashtable{  
  70. public:  
  71.     typedef HashFcn hasher;  
  72.     typedef EqualKey key_equal;  
  73.     typedef value value_type;  
  74.     typedef key key_type;  
  75.     typedef value_type& reference;  
  76.     typedef size_t size_type;  
  77.     typedef _hash_node<value> node;  
  78.     typedef _hashtable_iterator<value,key,HashFcn,EqualKey> iterator;  
  79.     vector<node*> buckets;  
  80. private:  
  81.     hasher hash; //哈希映射函数  
  82.     key_equal equals;  
  83.     size_type num_elements;  
  84. private:  
  85.     void initialize_buckets(size_type n){  
  86.         const size_type n_buckets = next_size(n);  
  87.         buckets.reserve(n_buckets);  
  88.         buckets.insert(buckets.end(), n_buckets, (node*) 0);  
  89.         num_elements = 0;  
  90.     }  
  91.     size_type next_size(size_type n)const{return _stl_next_prime(n);}  
  92.     void copy_from(const _hashtable& ht) {  
  93.         buckets.clear();  
  94.         buckets.reserve(ht.buckets.size());  
  95.         buckets.insert(buckets.end(), ht.buckets.size(), (node*) 0);  
  96.         try {  
  97.             for (size_type i = 0; i < ht.buckets.size(); ++i) {  
  98.                 if (const node* cur = ht.buckets[i]) {  
  99.                     node* copy = new_node(cur->val);  
  100.                     buckets[i] = copy;  
  101.    
  102.                     for (node* next = cur->next; next; cur = next, next = cur->next) {  
  103.                         copy->next = new_node(next->val);  
  104.                         copy = copy->next;  
  105.                     }  
  106.                 }  
  107.             }  
  108.             num_elements = ht.num_elements;  
  109.         }  
  110.         catch(...){  
  111.             clear();  
  112.         }  
  113.     }  
  114.     node* new_node(const value_type& obj)  
  115.     {  
  116.         node* n = allocate((node*)0);  
  117.         n->next = 0;  
  118.         try {  
  119.             construct(&n->val, obj);  
  120.             return n;  
  121.         }  
  122.         catch(...){  
  123.             deallocate(n);  
  124.             exit(1);  
  125.         }  
  126.     }  
  127.     template<class T>  
  128.     T* allocate(T* a,ptrdiff_t size=1){  
  129.         set_new_handler(0);  
  130.         T* tmp = (T*)(::operator new((size_t)(size*sizeof(T))));  
  131.         if(tmp == 0){  
  132.             cerr<<"out of memory."<<endl;  
  133.             exit(1);  
  134.         }  
  135.         return tmp;  
  136.     }  
  137.     template<class T1,class T2>  
  138.     void construct(T1* p,const T2& value){new (p)T1(value);}  
  139.     template<class T>  
  140.     void deallocate(T* buffer){::operator delete(buffer);}  
  141.     void clear(){  
  142.         for (size_type i = 0; i < buckets.size(); ++i) {  
  143.             node* cur = buckets[i];  
  144.             while (cur != 0) {  
  145.                 node* next = cur->next;  
  146.                 delete_node(cur);  
  147.                 cur = next;  
  148.             }  
  149.             buckets[i] = 0;  
  150.         }  
  151.         num_elements = 0;  
  152.     }  
  153.     void delete_node(node* n)  
  154.     {  
  155.         destroy(&n->val);  
  156.         deallocate(n);  
  157.     }  
  158.     template <class T>  
  159.     void destroy(T* pointer) {  
  160.         pointer->~T();  
  161.     }  
  162.     size_type bkt_num_key(const key_type& key)   
  163.     {  
  164.         return bkt_num_key(key, buckets.size());  
  165.     }  
  166.     size_type bkt_num_key(const key_type& key, size_t n)   
  167.     {  
  168.         return hash(key,n);// % n;  
  169.     }  
  170.     iterator insert_equal_noresize(const value_type& obj){  
  171.         size_type n = bkt_num(obj);  
  172.         node* first = buckets[n];  
  173.         for(node* cur=first;cur;cur=cur->next){  
  174.             if(equals(get_key(cur->val),get_key(obj))){  
  175.                 node* tmp = new_node(obj);  
  176.                 tmp->next = cur->next;  
  177.                 cur->next = tmp;  
  178.                 ++num_elements;  
  179.                 returniterator(tmp,this);  
  180.             }  
  181.         }  
  182.         node* tmp = new_node(obj);  
  183.         tmp->next = first;  
  184.         buckets[n] = tmp;  
  185.         return iterator(tmp,this);  
  186.     }  
  187.     pair<iterator, bool> insert_unique_noresize(const value_type& obj){  
  188.         const size_type n = bkt_num(obj);  
  189.         node* first = buckets[n];  
  190.    
  191.         for (node* cur = first; cur; cur = cur->next)   
  192.             if (equals(get_key(cur->val), get_key(obj)))  
  193.                 return pair<iterator, bool>(iterator(cur, this), false);  
  194.    
  195.         node* tmp = new_node(obj);  
  196.         tmp->next = first;  
  197.         buckets[n] = tmp;  
  198.         ++num_elements;  
  199.         return pair<iterator, bool>(iterator(tmp, this), true);  
  200.     }  
  201.     value_type get_key(const value_type& obj){  
  202.         ExtractKey<value_type> tmp;  
  203.         return tmp(obj);  
  204.     }  
  205. public:  
  206.     size_type bucket_size(){return buckets.size();}  
  207.     _hashtable(size_type n,const HashFcn& hf,const EqualKey& eql):hash(hf),equals(eql){  
  208.         initialize_buckets(n);  
  209.     }  
  210.     _hashtable(const _hashtable& ht):hash(ht.hash),equals(ht.equals),num_elements(0){  
  211.         copy_from(ht);  
  212.     }  
  213.     _hashtable(){clear();}  
  214.     size_type bucket_count()const{return buckets.size();}  
  215.     size_type max_bucket_count()const{return _stl_prime_list[_stl_num_primes - 1];}  
  216.     size_type elems_in_bucket(size_type bucket)const{  
  217.         size_type result = 0;  
  218.         for(*node cur = buckets[bucket];cur;cur = cur->next)  
  219.             result += 1;  
  220.         return result;  
  221.     }  
  222.     size_type bkt_num(const value_type& obj)  
  223.     {  
  224.         return bkt_num_key(get_key(obj));  
  225.     }  
  226.     size_type bkt_num(const value_type& obj, size_t n) const  
  227.     {  
  228.         return bkt_num_key(get_key(obj), n);  
  229.     }  
  230.     void resize(size_type num_elements_hint){  
  231.         _hashfcn_mod<value_type,value_type> hashfcn_mod;  
  232.         const size_type old_n = buckets.size();  
  233.         if(num_elements_hint > old_n){  
  234.             const size_type n = next_size(num_elements_hint);  
  235.             if(n > old_n){  
  236.                 vector<node*> tmp(n,(node*)0);  
  237.                 try{  
  238.                     for(size_type bucket=0;bucket<old_n;++bucket){  
  239.                         node* first = buckets[bucket];  
  240.                         while(first){  
  241.                             size_type new_bucket = hashfcn_mod(first->val,n);  
  242.                             buckets[bucket] = first->next;  
  243.                             first->next = tmp[new_bucket];  
  244.                             tmp[new_bucket] = first;  
  245.                             first = buckets[bucket];  
  246.                         }  
  247.                     }  
  248.                     buckets.swap(tmp);  
  249.                 }  
  250.                 catch(...){  
  251.                     for(size_type bucket=0;bucket<tmp.size();++bucket){  
  252.                         while(tmp[bucket]){  
  253.                             node* next = tmp[bucket]->next;  
  254.                             delete_node(tmp[bucket]);  
  255.                             tmp[bucket] = next;  
  256.                         }   
  257.                     }  
  258.                     throw;  
  259.                 }  
  260.             }  
  261.         }  
  262.     }  
  263.     pair<iterator,bool> insert_unique(const value_type& obj){  
  264.         resize(num_elements+1);  
  265.         return insert_unique_noresize(obj);  
  266.     }  
  267.     iterator insert_equal(const value_type& obj)  
  268.     {  
  269.         resize(num_elements + 1);  
  270.         return insert_equal_noresize(obj);  
  271.     }   
  272.     iterator begin()  
  273.     {   
  274.         for (size_type n = 0; n < buckets.size(); ++n)  
  275.             if (buckets[n])  
  276.                 return iterator(buckets[n], this);  
  277.         return end();  
  278.     }  
  279.     iterator end() { return iterator(0, this); }  
  280.     size_type erase(const key_type& key)  
  281.     {  
  282.         const size_type n = bkt_num_key(key);  
  283.         node* first = buckets[n];  
  284.         size_type erased = 0;  
  285.         if (first) {  
  286.             node* cur = first;  
  287.             node* next = cur->next;  
  288.             while (next) {  
  289.                 if (equals(get_key(next->val), key)) {  
  290.                     cur->next = next->next;  
  291.                     delete_node(next);  
  292.                     next = cur->next;  
  293.                     ++erased;  
  294.                     --num_elements;  
  295.                 }  
  296.                 else {  
  297.                     cur = next;  
  298.                     next = cur->next;  
  299.                 }  
  300.             }  
  301.             if (equals(get_key(first->val), key)) {  
  302.                 buckets[n] = first->next;  
  303.                 delete_node(first);  
  304.                 ++erased;  
  305.                 --num_elements;  
  306.             }  
  307.         }  
  308.         return erased;  
  309.     }  
  310.     void erase(const iterator& it)  
  311.     {  
  312.         if (node* const p = it.cur) {  
  313.             const size_type n = bkt_num(p->val);  
  314.             node* cur = buckets[n];  
  315.    
  316.             if (cur == p) {  
  317.                 buckets[n] = cur->next;  
  318.                 delete_node(cur);  
  319.                 --num_elements;  
  320.             }  
  321.             else {  
  322.                 node* next = cur->next;  
  323.                 while (next) {  
  324.                     if (next == p) {  
  325.                         cur->next = next->next;  
  326.                         delete_node(next);  
  327.                         --num_elements;  
  328.                         break;  
  329.                     }  
  330.                     else {  
  331.                         cur = next;  
  332.                         next = cur->next;  
  333.                     }  
  334.                 }  
  335.             }  
  336.         }  
  337.     }  
  338.     reference find_or_insert(const value_type& obj){  
  339.         resize(num_elements + 1);  
  340.         size_type n = bkt_num(obj);  
  341.         node* first = buckets[n];  
  342.    
  343.         for (node* cur = first; cur; cur = cur->next)  
  344.             if (equals(get_key(cur->val), get_key(obj)))  
  345.         return cur->val;  
  346.    
  347.         node* tmp = new_node(obj);  
  348.         tmp->next = first;  
  349.         buckets[n] = tmp;  
  350.         ++num_elements;  
  351.         return tmp->val;  
  352.     }  
  353.     iterator find(const key_type& key){  
  354.         size_type n = bkt_num_key(key);  
  355.         node* first;  
  356.         for ( first = buckets[n];first && !equals(get_key(first->val), key);  
  357.             first = first->next);  
  358.         return iterator(first, this);  
  359.     }   
  360.     void erase(iterator first, iterator last){  
  361.         size_type f_bucket = first.cur ? bkt_num(first.cur->val) : buckets.size();  
  362.         size_type l_bucket = last.cur ? bkt_num(last.cur->val) : buckets.size();  
  363.         if (first.cur == last.cur)return;  
  364.         else if (f_bucket == l_bucket)erase_bucket(f_bucket, first.cur, last.cur);  
  365.         else {  
  366.             erase_bucket(f_bucket, first.cur, 0);  
  367.             for (size_type n = f_bucket + 1; n < l_bucket; ++n)  
  368.                 erase_bucket(n, 0);  
  369.             if (l_bucket != buckets.size())  
  370.                 erase_bucket(l_bucket, last.cur);  
  371.         }  
  372.     }  
  373. };  
  374. /***************************************************** 
  375. 此函数对象用于定义映射函数,根据自己的需求可以定义线性探测、 
  376. 二次线性探测或者自定义函数 
  377. ***********************************************************/  
  378. template<class T1,class T2>  
  379. class _hashfcn_mod{ //简单取余映射   
  380. public:  
  381.     T1 operator()(T1 value,T2 size){ //value为key值  size为bucket长度  
  382.         return value % size;  
  383.     }  
  384. };  
  385.   
  386. /************************************************************* 
  387. 判断键值是否相等的函数,可自定义 
  388. *************************************************************/  
  389. template<class T>  
  390. class _key_equal{  
  391. public:  
  392.     bool operator()(T t1,T t2){  
  393.         return t1 == t2;  
  394.     }  
  395. };  
  396.   
  397. /************************************************************ 
  398. 从节点中取出键值的方法,可自定义 
  399. ***********************************************************/  
  400. template<class T>  
  401. class ExtractKey{  //从节点取出键值  
  402. public:  
  403.     T operator()(const T& tmp){  
  404.         identity<T> id;  
  405.         return id(tmp);  
  406.     }  
  407. };  
  408.   
  409. void test1(){  
  410.     _hashfcn_mod<int,int> hashfcn;  
  411.     _key_equal<int> keyequal;  
  412.     _hashtable<int,int,_hashfcn_mod<int,int>,_key_equal<int>> hashtab(20,hashfcn,keyequal);  
  413.     hashtab.insert_unique(15);  
  414.     hashtab.insert_unique(14);  
  415.     hashtab.insert_unique(13);  
  416.     hashtab.insert_unique(12);  
  417.     _hashtable<int,int,_hashfcn_mod<int,int>,_key_equal<int>>::iterator iter;  
  418.     for(iter = hashtab.begin();iter!= hashtab.end();++iter)  
  419.         cout<<*iter<<" ";  
  420.     cout<<endl;  
  421.     hashtab.erase(12);  
  422.     for(iter = hashtab.begin();iter!= hashtab.end();++iter)  
  423.         cout<<*iter<<" ";  
  424.     cout<<endl;  
  425.     hashtab.erase(hashtab.find(13));  
  426.     for(iter = hashtab.begin();iter!= hashtab.end();++iter)  
  427.         cout<<*iter<<" ";  
  428.     cout<<endl;  
  429. }  
  430. int main(){  
  431.     test1();  
  432. }  
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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值