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

程序功能:

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
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值