1)冲突解决方式,通过链表解决
2)slot数组中是否保存数据的问题,这个是一个容易让人困惑的问题,解决方案是slot不是HashNode的数组,而是一组指向HashNode的指针,因此slot数组中肯定不会保存数据
3)slot大小的选择,在HashTable的构造函数中设定大小,但hash函数使用了乘法策略,因此需要找到一个2^p>用户给的size的p,以2^p作为size,但存在这样的情况,如果用户给定大小size=33,实际的大小为64,最多是用户给定大小的2倍。
4)哈希函数使用乘法策略计算
5)Find函数返回的时Iterator,而不是ValueType类型的数据,主要是当Find失败时,如果返回ValueType类型的数据,不知道应该返回什么数据,不方
便用户进行判断,而参考std::map的实现,返回一个Itertor则要方便的多
6)重载了[]操作符,可以同时满足检索、插入和赋值
具体代码如下:
#include <stdio.h>
#include <string>
template<typename KeyType, typename ValueType>
class HashNode {
public:
HashNode() : next_(NULL) {}
HashNode(const KeyType& key, const ValueType& value) : key_(key), value_(value), next_(NULL) {}
KeyType key_;
ValueType value_;
HashNode<KeyType, ValueType>* next_;
};
template<typename KeyType, typename ValueType>
class HashMap {
public:
class Iterator {
public:
Iterator(HashMap* hash_map, int offset, HashNode<KeyType, ValueType>* current) : hash_map_(hash_map), offset_(offset), current_(current) {
if (!current_) {
while (offset_ < hash_map_->slots_size_ && !hash_map->slots_[offset_]) {
offset_++;
}
current_ = hash_map->slots_[offset_];
}
}
KeyType& First() {
if (current_) {
return current_->key_;
}
}
ValueType& Second() {
if (current_) {
return current_->value_;
}
}
bool operator!=(const Iterator& right) {
return !((offset_ == right.offset_) && (current_ == right.current_));
}
private:
HashMap* hash_map_;
int offset_;
HashNode<KeyType, ValueType>* current_;
};
HashMap() {
HashMap(100);
}
HashMap(size_t size) {
slots_size_ = 1;
slots_bits_ = 0;
while ((slots_size_ <<= 1) <= size) {
slots_bits_++;
}
slots_ = new HashNode<KeyType, ValueType>*[slots_size_];
for (int i = 0; i < slots_size_; ++i) {
slots_[i] = NULL;
}
printf("slot_size:%d \n", slots_size_);
}
Iterator Find(const KeyType& key) {
unsigned int code = HashFun(key);
HashNode<KeyType, ValueType>* current = slots_[code];
while (current) {
if (current->key_ == key) {
return Iterator(this, code, current);
}
current = current->next_;
}
return Iterator(this, slots_size_, NULL);
}
Iterator End() {
return Iterator(this, slots_size_, NULL);
}
ValueType& operator[](KeyType key) {
Iterator it = Find(key);
if (it != End()) {
return it.Second();
}
unsigned int code = HashFun(key);
ValueType value;
HashNode<KeyType, ValueType>* slot = new HashNode<KeyType, ValueType>(key, value);
slot->next_ = slots_[code];
slots_[code] = slot;
return slot->value_;
}
private:
unsigned int HashFun(unsigned int key) {
const int fibonacci = 2654435769;
unsigned int code = (key * fibonacci) >> (32 - slots_bits_);
// printf("hashcode:%d %d\n", code, 32 - slots_bits_);
return code;
}
HashNode<KeyType, ValueType>** slots_;
int slots_size_;
int slots_bits_;
};
std::string Itoa(int value, int radix, std::string* s) {
(*s) = "";
static char character[] = "0123456789ABCDEF";
if (value < 0) {
(*s) = "-";
value *= -1;
}
do {
(*s) += character[value % radix];
} while ((value /= radix) >0);
int start = 0;
int end = (*s).size() - 1;
if ((*s).size() >0 && (*s)[0] == '-') {
start = 1;
}
char tmp;
while (start < end) {
tmp = (*s)[start];
(*s)[start] = (*s)[end];
(*s)[end] = tmp;
start++;
end--;
}
return *s;
}
int main(int argc, char** argv) {
HashMap<int,std::string> hash_table(1000000);
const int kKeySize = 10000;
std::string s;
for (int i = 0; i < kKeySize; ++i) {
Itoa(i, 10, &s);
hash_table[i] = s;
}
for(int i = 0; i < kKeySize; ++i) {
printf("%s\n", hash_table[i].c_str());
}
}
还没有解决的问题是:目前key的类型只能是int,需要把给定类型转换成int数值。