LOADFACTOR/AddressList_Hash/Hash.cpp

194 lines
5.2 KiB
C++
Raw Permalink Normal View History

2023-02-07 04:11:57 +00:00
#include "Hash.h"
using namespace std;
//对字符串进行散列,使用链地址法解决冲突
//返回大于n的下一个素数
int NextPrime(int n) {
int i;
int p = (n % 2) ? n + 2 : n + 1; //从大于n的第一个奇数开始
while (p <= MAXCAPACITY) {
for (i = (int)sqrt(p); i > 2; i--)
if (!(p % i))
break;
if (i == 2)
break;
else
p += 2;
}
return p;
}
void InitHashTable(HashTable &hash_table, int init_capacity) {
if (init_capacity > 0 && init_capacity < MAXCAPACITY)
hash_table.capacity = NextPrime(init_capacity);
else
hash_table.capacity = NextPrime(32);
hash_table.table = new Node[hash_table.capacity];
hash_table.size = 0;
for (int i = 0; i < hash_table.capacity; i++) {
hash_table.table[i].next = NULL;
}
}
unsigned int SumHash(const char *key, int table_size) {
unsigned int h = 0;
while (*key)
h += *key++;
return h % table_size;
}
unsigned int ShiftHash(const char *key, int table_size) {
unsigned int h = 0;
while (*key)
h = (h << 5) + *key++;
return h % table_size;
}
unsigned int ELFHash(const char *key, int table_size) {
unsigned long h = 0;
unsigned long x = 0;
while (*key) {
h = (h << 4) + (*key++); //h左移4位当前字符ASCII存入h的低四位
if ((x = h & 0xF0000000L) != 0) {
//如果最高位不为0则说明字符多余7个如果不处理再加第九个字符时第一个字符会被移出
//因此要有如下处理
h ^= (x >> 24);
//清空28~31位
h &= ~x;
}
}
return h % table_size;
}
void ReCapacity(HashTable &hash_table, unsigned int (*Hash)(const char *key, int table_size)) {
const int ori_capacity = hash_table.capacity;
hash_table.capacity = NextPrime(hash_table.capacity * 2);
Node *ori_table = hash_table.table;
hash_table.table = new Node[hash_table.capacity];
for (int i = 0; i < hash_table.capacity; i++) {
hash_table.table[i].next = NULL;
}
for (int i = 0; i < ori_capacity; i++) {
Node *p = ori_table[i].next, *q;
while (p) {
q = p;
p = p->next;
int new_pos = Hash(q->key, hash_table.capacity);
q->next = hash_table.table[new_pos].next;
hash_table.table[new_pos].next = q;
}
}
delete[] ori_table;
}
//将以key为键的元素value放入Hash表返回是否有旧元素有返回true使用value进行替换否则返回falseold_value为旧元素
bool Put(HashTable &hash_table, const char *key, ElemType value, ElemType &old_value, unsigned int (*Hash)(const char *key, int table_size)) {
//若添加新元素后使得元素个数等于哈希表容量*装填因子,进行扩容
if (hash_table.size + 1 >= hash_table.capacity * LOADFACTOR)
ReCapacity(hash_table, Hash);
unsigned int pos = Hash(key, hash_table.capacity);
Node *p = hash_table.table[pos].next;
while (p) {
if (!strcmp(p->key, key)) {
old_value = p->value;
p->value = value;
return true;
}
p = p->next;
}
Node *node = new Node;
strcpy(node->key, key);
node->value = value;
node->next = hash_table.table[pos].next;
hash_table.table[pos].next = node;
hash_table.size++;
return false;
}
bool Get(HashTable &hash_table, const char *key, ElemType &value, unsigned int (*Hash)(const char *key, int table_size)) {
int pos = Hash(key, hash_table.capacity);
Node *p = hash_table.table[pos].next;
while (p) {
if (!strcmp(key, p->key)) {
value = p->value;
return true;
}
p = p->next;
}
return false;
}
double GetASL(HashTable &hash_table, unsigned int (*Hash)(const char *key, int table_size)) {
double asl = 0.0;
for (int i = 0; i < hash_table.capacity; i++) {
int n = 0;
Node *p = hash_table.table[i].next;
while (p) {
asl += (++n);
p = p->next;
}
}
return asl / hash_table.size;
}
bool Remove(HashTable &hash_table, const char *key, ElemType &value, unsigned int (*Hash)(const char *key, int table_size)) {
int pos = Hash(key, hash_table.capacity);
Node *p = &hash_table.table[pos];
while (p ->next) {
if (!strcmp(p->next->key, key)) {
value = p->next->value;
Node *t = p->next;
p->next = t->next;
delete t;
return true;
}
p = p->next;
}
return false;
}
void DelHashTable(HashTable &hash_table) {
for (int i = 0; i < hash_table.capacity; i++) {
Node *p = hash_table.table[i].next;
while (p) {
Node *t = p;
p = p->next;
delete t;
}
}
delete[] hash_table.table;
}
void TraverseHashTable(HashTable &hash_table, void (*visit)(ElemType v)) {
for (int i = 0; i < hash_table.capacity; i++) {
Node *p = hash_table.table[i].next;
while (p) {
visit(p->value);
p = p->next;
}
}
}