您的位置:首页 > 编程语言 > C语言/C++

C++复习之HashTable的简单实现

2016-07-29 11:52 441 查看
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  hashtable C++