程序功能:
1.封装哈希表(Hash)
2.以及实现了迭代器(iterator)
3.允许string类,整形变量,浮点形变量,字符型变量等作为key值
废话不多说,马上上源码
Hash.h
/* * Name: Hash * Date: 14-12-2015 * Author: Sumkee * Brief: 哈希模组 * 1.能把string类,整形,浮点形,字符型变量当作key * 2.而且还实现了属于自己得迭代器(iterator) * */ #ifndef __HASH_H_ #define __HASH_H_ #include <cstdio> #include <cstdlib> #include <cstring> #include <iostream> #include <stdint.h> #include <iterator> using namespace std; template<typename __Key, typename __Value> class Hash { public: enum { MaxKey = 10000000, // 最大可存储数据 MaxCharLenght = 128, // 最长字符串 }; Hash(); Hash(Hash<__Key, __Value> &src); ~Hash(); // 访问函数 inline size_t count() { return m_val_count; } inline size_t table_size() { return m_tb_size; }; // 查看key值相对应得数据 const __Value operator[](__Key key) { long index; if((index = __hash_keyindex_by_key(key, hash_keyindex(key))) > -1) return m_table[index]; else return *m_empty; } // 如上 const __Value value(__Key key) { long index; if((index = __hash_keyindex_by_key(key, hash_keyindex(key))) > -1) return m_table[index]; else return *m_empty; } // 查看key值是否存在 bool has_key(__Key key) { return __hash_keyindex_by_key(key, hash_keyindex(key)) > -1; } // 用数据逆向查看相对应的key值 __Key key(__Value val); // 写入或修改函数 void insert(__Key key, __Value val); void insert(pair<__Key, __Value> &key_and_val); void remove(__Key key); void operator=(Hash<__Key,__Value> &src); void clear(); // 迭代器(用法和stl里提供的一样) class __Iterator; typedef __Iterator iterator; // 迭代器开始 __Iterator begin() { int i=0; for(; i< m_tb_size && !m_is_setted[i]; ++i); return iterator(this, i); } // 迭代器结束 __Iterator end() { return iterator(this, m_tb_size); } private: __Value *m_table; // 哈希key值所对应数据表 __Key *m_keys; // 哈希key值所对应的所有key数据 bool *m_is_setted; // 查看m_table或m_keys的某下标是否已插入数据 long m_tb_size; // 哈希数据表大小,也就是m_table或m_keys的大小 long m_val_count; // 已插入数据总数 __Value *m_oldtable; __Key *m_oldkeys; bool *m_old_issetted; long m_old_tbsize; __Value *m_empty; // 空的数据变量,用来返回空变量时用的 /* Name: hash_keyindex * Brief: 透过哈希key值来获取数据所在位置的下标,也就是m_table[index]; * 不过这个函数主要判断key是否符合类型,除了下面得数据,其他会出错; * 它进一步获取下标是通过__hash_keyindex实现。 * return: 返回key值所对应的下标 */ long hash_keyindex(int8_t); long hash_keyindex(int16_t); long hash_keyindex(int32_t); long hash_keyindex(int64_t); long hash_keyindex(uint8_t); long hash_keyindex(uint16_t); long hash_keyindex(uint32_t); long hash_keyindex(uint64_t); long hash_keyindex(float); long hash_keyindex(double); long hash_keyindex(string &); long __hash_keyindex(u_char *first, size_t size); /* Name: __hash_null_keyindex * Brief: hash_keyindex是获取下标,不确定下标是否已经被占用; * 如果要确保下标是未被占用的,就需要调用hash_keyindex后, * 再调用__hash_null_keyindex。 * return: 返回key值所对应的下标 */ long __hash_null_keyindex(__Key &key, long key_index); /* Name: __hash_keyindex_by_key * Brief: 获取key值所在的下标,而且key值必须是存在的,也就是查找函数(value(),[]())的核心。 * 在调用此函数之前也需要调用hash_keyindex函数。 * return: 如果key值存在,就返回下标;否则返回-1 */ long __hash_keyindex_by_key(__Key &key, long key_index); /* Name: reallocate * Brief: 为m_tables, m_keys, m_is_setted等数据重新分配内存 */ void reallocate(long size); /* Name: need_rehash, rehash * Brief: need_rehash是判断是否有需要重新分配更大的内存, * 如果有需要得话它会调用reallocate,而reallocate在重新 * 分配完内存后就会调用rehash将旧的数据重新用哈希的方法 * 存放到新分配的内存地址,从而确保数据不丢失。 */ void need_rehash(); void rehash(); /* Name: put_error * Brief: 输出错误信息 */ void put_error(string str) { cout << "Hash:" << str << endl; } }; #endif
Hash.cpp
#include "hash.h" template<typename __Key, typename __Value> Hash<__Key, __Value>::Hash() : m_keys(0), m_table(0) ,m_is_setted(0), m_tb_size(0), m_val_count(0), m_empty(0) { // 初始化,默认表大小为10 reallocate(10); } template<typename __Key, typename __Value> Hash<__Key, __Value>::Hash(Hash<__Key, __Value> &src) : m_keys(0), m_table(0) ,m_is_setted(0),m_tb_size(0),m_val_count(0), m_empty(0) { // 初始化,将别的Hash类复制过来 reallocate(src.m_tb_size); for(int i=0; i<src.m_tb_size; ++i) { if(src.m_is_setted[i]) { insert(src.m_keys[i], src.m_table[i]); } } } template<typename __Key, typename __Value> Hash<__Key, __Value>::~Hash() { // 释放内存 clear(); } template<typename __Key, typename __Value> void Hash<__Key, __Value>::operator=(Hash<__Key,__Value> &src) { // 释放内存 clear(); // 将别的Hash类复制过来 reallocate(src.m_tb_size); for(int i=0; i<src.m_tb_size; ++i) { if(src.m_is_setted[i]) { insert(src.m_keys[i], src.m_table[i]); } } } template<typename __Key, typename __Value> void Hash<__Key, __Value>::clear() { if(m_keys) delete [] m_keys; if(m_table) delete [] m_table; if(m_is_setted) delete [] m_is_setted; if(m_empty) delete m_empty; m_keys = 0; m_table = 0; m_is_setted = 0; m_empty = 0; m_tb_size = 0; m_val_count = 0; reallocate(10); } template<typename __Key, typename __Value> __Key Hash<__Key, __Value>::key(__Value val) { for(int i=0; i<m_tb_size; ++i) { if(m_is_setted[i]) { if(val == m_table[i]) { return m_keys[i]; } } } } template<typename __Key, typename __Value> long Hash<__Key,__Value>::hash_keyindex(int8_t key) { u_char *p = reinterpret_cast<u_char*>(&key); return __hash_keyindex(p, sizeof(int8_t)); } template<typename __Key, typename __Value> long Hash<__Key, __Value>::hash_keyindex(int16_t key) { u_char *p = reinterpret_cast<u_char*>(&key); return __hash_keyindex(p, sizeof(int16_t)); } template<typename __Key, typename __Value> long Hash<__Key, __Value>::hash_keyindex(int32_t key) { u_char *p = reinterpret_cast<u_char*>(&key); return __hash_keyindex(p, sizeof(int32_t)); } template<typename __Key, typename __Value> long Hash<__Key, __Value>::hash_keyindex(int64_t key) { u_char *p = reinterpret_cast<u_char*>(&key); return __hash_keyindex(p, sizeof(int64_t)); } template<typename __Key, typename __Value> long Hash<__Key, __Value>::hash_keyindex(uint8_t key) { u_char *p = reinterpret_cast<u_char*>(&key); return __hash_keyindex(p, sizeof(uint8_t)); } template<typename __Key, typename __Value> long Hash<__Key, __Value>::hash_keyindex(uint16_t key) { u_char *p = reinterpret_cast<u_char*>(&key); return __hash_keyindex(p, sizeof(uint16_t)); } template<typename __Key, typename __Value> long Hash<__Key, __Value>::hash_keyindex(uint32_t key) { u_char *p = reinterpret_cast<u_char*>(&key); return __hash_keyindex(p, sizeof(uint32_t)); } template<typename __Key, typename __Value> long Hash<__Key, __Value>::hash_keyindex(uint64_t key) { u_char *p = reinterpret_cast<u_char*>(&key); return __hash_keyindex(p, sizeof(uint64_t)); } template<typename __Key, typename __Value> long Hash<__Key, __Value>::hash_keyindex(float key) { u_char *p = reinterpret_cast<u_char*>(&key); return __hash_keyindex(p, sizeof(float)); } template<typename __Key, typename __Value> long Hash<__Key, __Value>::hash_keyindex(double key) { u_char *p = reinterpret_cast<u_char*>(&key); return __hash_keyindex(p, sizeof(double)); } template<typename __Key, typename __Value> long Hash<__Key, __Value>::hash_keyindex(string &key) { char tmp_data[MaxCharLenght] = {0}; ::memcpy(tmp_data, key.data(), key.size()); return __hash_keyindex((u_char*)tmp_data, key.size()); } template<typename __Key, typename __Value> long Hash<__Key, __Value>::__hash_keyindex(u_char *first, size_t size) { // 这里就是哈希算法,透过key值来查找下标 ulong result=0; while(size--) { result = *first++ ^ result*0x1579532586542ul; result *= 0x35715ul; } return result%m_tb_size; } template<typename __Key, typename __Value> long Hash<__Key, __Value>::__hash_null_keyindex(__Key &key, long key_index) { while(1) { key_index = (key_index+1) % m_tb_size; if(!m_is_setted[key_index] || m_keys[key_index]==key) { return key_index; } } } template<typename __Key, typename __Value> long Hash<__Key, __Value>::__hash_keyindex_by_key(__Key &key, long key_index) { long end = key_index; do { key_index = (key_index+1) % m_tb_size; if(m_is_setted[key_index] && m_keys[key_index]==key) { return key_index; } else if(!m_is_setted[key_index]) { break; } } while (key_index != end); return -1; } template<typename __Key, typename __Value> void Hash<__Key, __Value>::reallocate(long size) { if(size > MaxKey) { put_error("too many key"); return; } // 分配一个空数据 if(m_empty == 0) { m_empty = new __Value; } // 保存旧数据 m_oldkeys = m_keys; m_oldtable = m_table; m_old_issetted = m_is_setted; m_old_tbsize = m_tb_size; // 申请新内存空间 try { m_keys = new __Key[size]; m_table = new __Value[size]; m_is_setted = new bool[size]; m_val_count = 0; if(!m_keys || !m_table || !m_is_setted) { throw "memory allocation error"; } ::memset(m_is_setted, 0, size*sizeof(bool)); m_tb_size = size; } catch(string err) { put_error(err); } // 将旧数据复制到新内存空间 rehash(); // 释放旧数据的内存空间 delete [] m_oldkeys; delete [] m_oldtable; delete m_old_issetted; m_old_tbsize = 0; } template<typename __Key, typename __Value> void Hash<__Key, __Value>::need_rehash() { if(m_tb_size >= MaxKey) { return; } // 如果当前数据表空间的占用达到七成,就要重新分多一倍得空间出来 double ratio = (double)m_val_count/m_tb_size; if(ratio >= 0.7) { long size = m_tb_size*2; size = size >= MaxKey ? MaxKey : size; reallocate(size); } } template<typename __Key, typename __Value> void Hash<__Key, __Value>::rehash() { // 将旧数据复制新内存空间 for(int i=0; i<m_old_tbsize; ++i) { if(m_old_issetted[i]) { insert(m_oldkeys[i],m_oldtable[i]); } } } template<typename __Key, typename __Value> void Hash<__Key, __Value>::insert(__Key key, __Value val) { if(m_val_count >= MaxKey) { put_error("too many key"); return; } // 判断是否需要重新分配内存 need_rehash(); // 插入 long new_key_index = __hash_null_keyindex(key, hash_keyindex(key)); if(m_keys[new_key_index] == key && m_is_setted[new_key_index]) { // 如果对应的key值已经存在,就修改对应得数据 m_table[new_key_index] = val; } else { // 插入key值,数据,和将下标设为已占用 m_table[new_key_index] = val; m_keys[new_key_index] = key; m_is_setted[new_key_index] = true; ++m_val_count; } } template<typename __Key, typename __Value> void Hash<__Key, __Value>::insert(pair<__Key, __Value> &key_and_val) { insert(key_and_val.first, key_and_val.second); } template<typename __Key, typename __Value> void Hash<__Key, __Value>::remove(__Key key) { // 删除key值对应的数据,其实就是将其下标设为未占用而已 long key_index = __hash_keyindex_by_key(key, hash_keyindex(key)); if(key_index != -1) { m_is_setted[key_index] = false; --m_val_count; } } // 这个就是迭代器的类 template<typename __Key, typename __Value> class Hash<__Key, __Value>::__Iterator : public std::iterator<std::input_iterator_tag, std::pair<__Key, __Value> > { Hash<__Key, __Value> *phash; // 指向hash类 long hash_index; // 当前下标,指向key值和数据 pair<__Key, __Value> hash_data; // 将要返回的key值和数据塞进里面 public: __Iterator() : phash(0) , hash_index(0) {} __Iterator(Hash<__Key, __Value> *p, long i) : phash(p) , hash_index(i) {} // 前置递增, 将hash_index定位到下一个已存在得下标 const __Iterator operator++() { int i; for(i=hash_index+1; i<phash->m_tb_size; ++i) { if(phash->m_is_setted[i]) { break; } } hash_index = i; return *this; } // 后置递增, 也是将hash_index定位到下一个已存在得下标 const __Iterator operator++(int) { __Iterator old(*this); int i; for(i=hash_index+1; i<phash->m_tb_size; ++i) { if(phash->m_is_setted[i]) { break; } } hash_index = i; return old; } bool operator==(__Iterator iter) { return (iter.phash==phash) && (iter.hash_index==iter.hash_index); } bool operator!=(__Iterator iter) { return (iter.phash!=phash) || (hash_index!=iter.hash_index); } // 利用hash_index获取key值和数据,打包成pair类,最后返回 const pair<__Key,__Value> operator*() { return pair<__Key&, __Value&>(phash->m_keys[hash_index], phash->m_table[hash_index]); } const pair<__Key,__Value>* operator->() { hash_data.first = phash->m_keys[hash_index]; hash_data.second = phash->m_table[hash_index]; return &hash_data; } }; /***************************************************/ // 测试 int main() { Hash<string, string> hash; hash.insert("a", "apple"); hash.insert("b", "boy"); hash.insert("c", "cat"); hash.insert("d", "dog"); hash.insert("f", "fire"); // 查找 cout << hash["a"] << endl; cout << hash["c"] << endl; cout << hash["f"] << endl; // 删除 hash.remove("c"); cout << "not cat:" << hash["c"] << endl; // 利用迭代器遍历 Hash<string,string>::iterator iter = hash.begin(); for(; iter !=hash.end() ;++iter) { cout << iter->first << ":" << iter->second << endl; } return 0; }
备注:本人编程新手,有错误请多多指点,谢谢。