1. hashtable.h
#ifndef HASHTABLE_H
#define HASHTABLE_H
#include <iostream>
#include <string>
#include <string.h>
#include <stdint.h>
struct Handle {
std::string key;
uint32_t hash;
Handle* next_hash;
Handle(std::string k, uint32_t h) : key(k), hash(h), next_hash(NULL) { }
};
class HashTable {
public:
HashTable() : length_(0), elems_(0), list_(NULL) { Resize(); }
~HashTable() { delete[] list_; }
Handle* Lookup(std::string key, uint32_t hash);
Handle* Insert(Handle* h);
Handle* Remove(std::string key, uint32_t hash);
void Resize();
void Internal();
private:
Handle** FindPointer(std::string key, uint32_t hash);
uint32_t length_;
uint32_t elems_;
Handle** list_;
};
#endif
hashtable.cc:
#include "hashtable.h"
void HashTable::Internal() {
std::cout << "length_ = " << length_
<< " elems_ = " << elems_ << std::endl;
for (int i = 0; i < length_; ++i) {
Handle* h = list_[i];
if (h != NULL) {
std::cout << h->key << " => " << h ->hash << "\t";
while ((h = h->next_hash) != NULL) {
std::cout << h->key << " => " << h ->hash << "\t";
}
std::cout << std::endl;
} else {
std::cout << "0x0" << std::endl;
}
}
}
void HashTable::Resize() {
uint32_t new_length = 4;
while (new_length < elems_) {
new_length <<= 1;
}
Handle** new_list = new Handle* [new_length];
memset(new_list, 0, new_length);
for (uint32_t i = 0; i < length_; ++i) {
Handle* h = list_[i];
// edtion of tail insert
/*
while (h != NULL) {
Handle** ptr = &new_list[h->hash & (new_length - 1)];
Handle* next = h->next_hash;
while (*ptr != NULL) {
ptr = &(*ptr)->next_hash;
}
h->next_hash = *ptr;
*ptr = h;
h = next;
}*/
// edtion of head insert
while (h != NULL) {
Handle* next = h->next_hash;
Handle** ptr = &new_list[h->hash & (new_length - 1)];
h->next_hash = *ptr;
*ptr = h;
h = next;
}
}
delete[] list_;
list_ = new_list;
length_ = new_length;
std::cout << "for resize: ";
Internal();
}
Handle** HashTable::FindPointer(std::string key, uint32_t hash) {
Handle** ptr = &list_[hash & (length_ - 1)];
while (*ptr != NULL && ((*ptr)->key != key || (*ptr)->hash != hash)) {
ptr = &(*ptr)->next_hash;
}
return ptr;
}
Handle* HashTable::Remove(std::string key, uint32_t hash) {
Handle** ptr = FindPointer(key, hash);
Handle* result = *ptr;
if (result != NULL) {
*ptr = result->next_hash;
elems_--;
}
std::cout << "for Remove: ";
Internal();
return result;
}
Handle* HashTable::Insert(Handle* h) {
Handle** ptr = FindPointer(h->key, h->hash);
Handle* old = *ptr;
h->next_hash = (old == NULL ? NULL : old->next_hash);
*ptr = h;
if (old == NULL) {
elems_++;
std::cout << "for Insert: ";
Internal();
if (elems_ > length_) {
Resize();
}
}
return old;
}
Handle* HashTable::Lookup(std::string key, uint32_t hash) {
return *FindPointer(key, hash);
}
测试文件hashtable_test.cc:
#include <iostream>
#include "hashtable.h"
#include <stdlib.h>
#include <stdio.h>
void print(Handle*);
int main(int argc, char* argv[]) {
Handle ha("sdau", 2);
Handle hb("whu", 2);
Handle hc("pku", 2);
HashTable table;
table.Insert(&ha);
table.Insert(&hb);
table.Insert(&hc);
table.Remove(hb.key, hb.hash);
Handle* h = table.Lookup(hb.key, hb.hash);
h = table.Lookup(hc.key, hc.hash);
print(h);
std::string vv("weibo");
char buf[10];
for (int i = 0; i < 9 - 4; ++i) {
sprintf(buf, "%d", i);
Handle* hi = new Handle(vv + buf, ((i + 1) % 5 == 0 ? 2 : i));
table.Insert(hi);
}
return 0;
}
void print(Handle* h) {
std::cout << "for Lookup: " << std::endl;
if (h) {
std::cout << "found: " << h->key << " => " << h->hash << std::endl;
return;
}
std::cout << "not found ~" << std::endl;
}