C++ HashTable的简单实现

12 篇文章 1 订阅

hashtable :本文中采用开链法( separate chaining )来处理 “ 冲突 ” ( collision ),而且 hashtable只存储唯一的元素,不存在重复。

class hashtable {
public:
    //  构造函数, n 为想要构造的 hashtable 的 bucket 数量
    hashtable(size_t n);
    ~hashtable();
    //  插入元素。若元素不存在,插入成功返回 true ;若元素已存在则插入失败,返回 false
    bool insert(const int val);
    //  查找元素是否在表中出现
    bool find(const int val);
    //  删除元素。若元素存在,删除成功返回 true ;若元素不存在则删除失败,返回 false
    bool erase(const int val);
    //  清除所有元素
    void clear();
    //  返回已有元素数目
    size_t size();
private:
    // bucket 中的节点
    struct hashtable_node {
        hashtable_node *next;
        int val;
        hashtable_node(int _val, hashtable_node *_next = NULL) :
                val(_val), next(_next) {
        }
    };

    hashtable(const hashtable & h); //  暂时不允许拷贝和赋值
    const hashtable & operator =(const hashtable & h);
    // hash 函数
    size_t hash(unsigned long x);
    //  寻找大于等于 n 且最接近 n 的质数
    unsigned long next_prime(unsigned long n);
    // bucket 向量表
    vector<hashtable_node*> buckets;
    //  元素个数
    size_t num_elements;
};
hashtable::hashtable(size_t n) {
    //  将 bucket 数量设置为大于等于 n 且最接近 n 的质数
    const size_t n_buckets = next_prime(n);
    buckets.reserve(n_buckets);
    buckets.insert(buckets.end(), n_buckets, NULL);
    num_elements = 0;
};
hashtable::~hashtable() {
    //  清除所有链中的节点
    clear();
}
bool hashtable::insert(const int val) {
    //  不重复插入。已存在,返回 false
    if (find(val))
        return false;
    //  调用 hash 函数获得 bucket 号
    const size_t k = hash(val);
    //  将新节点直接插入到链表头部
    hashtable_node * tmp = new hashtable_node(val);
    tmp->next = buckets[k];
    buckets[k] = tmp;
    ++num_elements;
    //  插入成功
    return true;
}
bool hashtable::find(const int val) {
    const size_t k = hash(val);
    hashtable_node *p = buckets[k];
    //  在对应的 bucket 中查找
    while (p != NULL) {
        if (p->val = val)
            return true;
        p = p->next;
    }
    return false;
}
bool hashtable::erase(const int val) {
    const size_t k = hash(val);
    hashtable_node *p = buckets[k];
    hashtable_node *pre = NULL;
    //  找到该节点
    while (p != NULL && p->val != val) {
        pre = p;
        p = p->next;
    }
    //  删除该节点
    if (p == NULL)
        return false;
    if (pre == NULL)
        buckets[k] = p->next; // 删除第一个节点
    else
        pre->next = p->next;
    delete p;
    return true;
}
void hashtable::clear() {
    //  清除所有链中的节点
    for (int i = 0; i < buckets.size(); i++) {
        hashtable_node *p = buckets[i];
        while (p != NULL) {
            hashtable_node *next = p->next;
            delete p;
            p = next;
        }
    }
}
size_t hashtable::size() {
    return num_elements;
}
size_t hashtable::hash(unsigned long x) {
    return x % buckets.size();
}
unsigned long hashtable::next_prime(unsigned long n) {
    static const int num_primes = 28;
    static const unsigned long prime_list[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 且最接近 n 的质数
    int i = 0;
    while (i < num_primes && prime_list[i] < n)
        i++;
    return i == num_primes ? prime_list[num_primes - 1] : prime_list[i];
}
// 如果是含头结点的情况
bool hashtable::erase(const int val) {
    const size_t k = hash(val);
    hashtable_node *p = buckets[k];
    hashtable_node *tmp = NULL;
//  找到该节点
    while (p->next != NULL && p->next->val != val) {
        p = p->next;
    }
    if (p->next == NULL)
        return false;
//  删除该节点
    tmp = p->next;
    p->next = tmp->next;
    delete tmp;
    return true;
}

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值