c++ 封装哈希表(Hash) 以及实现迭代器(iterator)

来源:互联网 发布:单片机原理经典教材 编辑:程序博客网 时间:2024/04/27 22:52

程序功能:

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;}


备注:本人编程新手,有错误请多多指点,谢谢。



0 0
原创粉丝点击