Update test_hash.c
This commit is contained in:
parent
a6505f3731
commit
b20768ff97
|
@ -1,294 +1,292 @@
|
||||||
|
|
||||||
/**
|
|
||||||
* @file: test_hash.c
|
|
||||||
* @brief: a application of test hash function
|
|
||||||
* @version: 3.0
|
|
||||||
* @author: Yao wenying
|
|
||||||
* @date: 2023/05/26
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <transform.h>
|
#include <transform.h>
|
||||||
#include"test_hash.h"
|
#include "test_hash.h"
|
||||||
|
|
||||||
|
// 默认的哈希函数,将字符串键转换为哈希码
|
||||||
int defaultHashCode(HashMap hashMap, let key) {
|
int defaultHashCode(HashMap hashMap, let key) {
|
||||||
char * k = (char *)key;
|
char * k = (char *)key;
|
||||||
unsigned long h = 0;
|
unsigned long h = 0;
|
||||||
while (*k) {
|
while (*k) {
|
||||||
h = (h << 4) + *k++;
|
h = (h << 4) + *k++;
|
||||||
unsigned long g = h & 0xF0000000L;
|
unsigned long g = h & 0xF0000000L;
|
||||||
if (g) {
|
if (g) {
|
||||||
h ^= g >> 24;
|
h ^= g >> 24;
|
||||||
}
|
}
|
||||||
h &= ~g;
|
h &= ~g;
|
||||||
}
|
}
|
||||||
return h % hashMap->listSize;
|
return h % hashMap->listSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 默认的键相等判断函数,比较两个字符串是否相等
|
||||||
Boolean defaultEqual(let key1, let key2) {
|
Boolean defaultEqual(let key1, let key2) {
|
||||||
return strcmp((string)key1, (string)key2) ? False : True;
|
return strcmp((string)key1, (string)key2) ? False : True;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 重置哈希表的大小
|
||||||
void resetHashMap(HashMap hashMap, int listSize) {
|
void resetHashMap(HashMap hashMap, int listSize) {
|
||||||
|
if (listSize < 8) return;
|
||||||
|
|
||||||
if (listSize < 8) return;
|
// 键值对临时存储空间
|
||||||
|
Entry tempList = newEntryList(hashMap->size);
|
||||||
|
|
||||||
// 键值对临时存储空间
|
HashMapIterator iterator = createHashMapIterator(hashMap);
|
||||||
Entry tempList = newEntryList(hashMap->size);
|
int length = hashMap->size;
|
||||||
|
for (int index = 0; hasNextHashMapIterator(iterator); index++) {
|
||||||
|
// 迭代取出所有键值对
|
||||||
|
iterator = nextHashMapIterator(iterator);
|
||||||
|
tempList[index].key = iterator->entry->key;
|
||||||
|
tempList[index].value = iterator->entry->value;
|
||||||
|
tempList[index].next = NULL;
|
||||||
|
}
|
||||||
|
freeHashMapIterator(&iterator);
|
||||||
|
|
||||||
HashMapIterator iterator = createHashMapIterator(hashMap);
|
// 清除原有键值对数据
|
||||||
int length = hashMap->size;
|
hashMap->size = 0;
|
||||||
for (int index = 0; hasNextHashMapIterator(iterator); index++) {
|
for (int i = 0; i < hashMap->listSize; i++) {
|
||||||
// 迭代取出所有键值对
|
Entry current = &hashMap->list[i];
|
||||||
iterator = nextHashMapIterator(iterator);
|
current->key = NULL;
|
||||||
tempList[index].key = iterator->entry->key;
|
current->value = NULL;
|
||||||
tempList[index].value = iterator->entry->value;
|
if (current->next != NULL) {
|
||||||
tempList[index].next = NULL;
|
while (current->next != NULL) {
|
||||||
}
|
Entry temp = current->next->next;
|
||||||
freeHashMapIterator(&iterator);
|
free(current->next);
|
||||||
|
current->next = temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 清除原有键值对数据
|
// 更改内存大小
|
||||||
hashMap->size = 0;
|
hashMap->listSize = listSize;
|
||||||
for (int i = 0; i < hashMap->listSize; i++) {
|
Entry relist = (Entry)realloc(hashMap->list, hashMap->listSize * sizeof(struct entry));
|
||||||
Entry current = &hashMap->list[i];
|
if (relist != NULL) {
|
||||||
current->key = NULL;
|
hashMap->list = relist;
|
||||||
current->value = NULL;
|
relist = NULL;
|
||||||
if (current->next != NULL) {
|
}
|
||||||
while (current->next != NULL) {
|
|
||||||
Entry temp = current->next->next;
|
|
||||||
free(current->next);
|
|
||||||
current->next = temp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更改内存大小
|
// 初始化数据
|
||||||
hashMap->listSize = listSize;
|
for (int i = 0; i < hashMap->listSize; i++) {
|
||||||
Entry relist = (Entry)realloc(hashMap->list, hashMap->listSize * sizeof(struct entry));
|
hashMap->list[i].key = NULL;
|
||||||
if (relist != NULL) {
|
hashMap->list[i].value = NULL;
|
||||||
hashMap->list = relist;
|
hashMap->list[i].next = NULL;
|
||||||
relist = NULL;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// 初始化数据
|
// 将所有键值对重新写入内存
|
||||||
for (int i = 0; i < hashMap->listSize; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
hashMap->list[i].key = NULL;
|
hashMap->put(hashMap, tempList[i].key, tempList[i].value);
|
||||||
hashMap->list[i].value = NULL;
|
}
|
||||||
hashMap->list[i].next = NULL;
|
free(tempList);
|
||||||
}
|
|
||||||
|
|
||||||
// 将所有键值对重新写入内存
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
hashMap->put(hashMap, tempList[i].key, tempList[i].value);
|
|
||||||
}
|
|
||||||
free(tempList);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 默认的键值对插入函数
|
||||||
void defaultPut(HashMap hashMap, let key, let value) {
|
void defaultPut(HashMap hashMap, let key, let value) {
|
||||||
// 获取哈希值
|
// 获取哈希值
|
||||||
int index = hashMap->hashCode(hashMap, key);
|
int index = hashMap->hashCode(hashMap, key);
|
||||||
|
|
||||||
if (hashMap->list[index].key == NULL) {
|
if (hashMap->list[index].key == NULL) {
|
||||||
hashMap->size++;
|
hashMap->size++;
|
||||||
// 该地址为空时直接存储
|
// 该地址为空时直接存储
|
||||||
hashMap->list[index].key = key;
|
hashMap->list[index].key = key;
|
||||||
hashMap->list[index].value = value;
|
hashMap->list[index].value = value;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
Entry current = &hashMap->list[index];
|
||||||
|
while (current != NULL) {
|
||||||
|
if (hashMap->equal(key, current->key)) {
|
||||||
|
// 对于键值已经存在的直接覆盖
|
||||||
|
current->value = value;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
current = current->next;
|
||||||
|
};
|
||||||
|
|
||||||
Entry current = &hashMap->list[index];
|
// 发生冲突则创建节点挂到相应位置的next上
|
||||||
while (current != NULL) {
|
Entry entry = newEntry();
|
||||||
if (hashMap->equal(key, current->key)) {
|
entry->key = key;
|
||||||
// 对于键值已经存在的直接覆盖
|
entry->value = value;
|
||||||
current->value = value;
|
entry->next = hashMap->list[index].next;
|
||||||
return;
|
hashMap->list[index].next = entry;
|
||||||
}
|
hashMap->size++;
|
||||||
current = current->next;
|
}
|
||||||
};
|
|
||||||
|
|
||||||
// 发生冲突则创建节点挂到相应位置的next上
|
if (hashMap->autoAssign && hashMap->size >= hashMap->listSize) {
|
||||||
Entry entry = newEntry();
|
// 内存扩充至原来的两倍
|
||||||
entry->key = key;
|
resetHashMap(hashMap, hashMap->listSize * 2);
|
||||||
entry->value = value;
|
}
|
||||||
entry->next = hashMap->list[index].next;
|
|
||||||
hashMap->list[index].next = entry;
|
|
||||||
hashMap->size++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hashMap->autoAssign && hashMap->size >= hashMap->listSize) {
|
|
||||||
|
|
||||||
// 内存扩充至原来的两倍
|
|
||||||
// *注: 扩充时考虑的是当前存储元素数量与存储空间的大小关系,而不是存储空间是否已经存满,
|
|
||||||
// 例如: 存储空间为10,存入了10个键值对,但是全部冲突了,所以存储空间空着9个,其余的全部挂在一个上面,
|
|
||||||
// 这样检索的时候和遍历查询没有什么区别了,可以简单这样理解,当我存入第11个键值对的时候一定会发生冲突,
|
|
||||||
// 这是由哈希函数本身的特性(取模)决定的,冲突就会导致检索变慢,所以这时候扩充存储空间,对原有键值对进行
|
|
||||||
// 再次散列,会把冲突的数据再次分散开,加快索引定位速度。
|
|
||||||
resetHashMap(hashMap, hashMap->listSize * 2);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 默认的获取值函数
|
||||||
let defaultGet(HashMap hashMap, let key) {
|
let defaultGet(HashMap hashMap, let key) {
|
||||||
if (hashMap->exists(hashMap, key)) {
|
if (hashMap->exists(hashMap, key)) {
|
||||||
int index = hashMap->hashCode(hashMap, key);
|
int index = hashMap->hashCode(hashMap, key);
|
||||||
Entry entry = &hashMap->list[index];
|
Entry entry = &hashMap->list[index];
|
||||||
while (entry != NULL) {
|
while (entry != NULL) {
|
||||||
if (hashMap->equal(entry->key, key)) {
|
if (hashMap->equal(entry->key, key)) {
|
||||||
return entry->value;
|
return entry->value;
|
||||||
}
|
}
|
||||||
entry = entry->next;
|
entry = entry->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 默认的删除键值对函数
|
||||||
let defaultRemove(HashMap hashMap, let key) {
|
let defaultRemove(HashMap hashMap, let key) {
|
||||||
int index = hashMap->hashCode(hashMap, key);
|
int index = hashMap->hashCode(hashMap, key);
|
||||||
Entry entry = &hashMap->list[index];
|
Entry entry = &hashMap->list[index];
|
||||||
if (entry->key == NULL) {
|
if (entry->key == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
let entryKey = entry->key;
|
let entryKey = entry->key;
|
||||||
Boolean result = False;
|
Boolean result = False;
|
||||||
if (hashMap->equal(entry->key, key)) {
|
if (hashMap->equal(entry->key, key)) {
|
||||||
hashMap->size--;
|
hashMap->size--;
|
||||||
if (entry->next != NULL) {
|
if (entry->next != NULL) {
|
||||||
Entry temp = entry->next;
|
Entry temp = entry->next;
|
||||||
entry->key = temp->key;
|
entry->key = temp->key;
|
||||||
entry->value = temp->value;
|
entry->value = temp->value;
|
||||||
entry->next = temp->next;
|
entry->next = temp->next;
|
||||||
free(temp);
|
free(temp);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
entry->key = NULL;
|
entry->key = NULL;
|
||||||
entry->value = NULL;
|
entry->value = NULL;
|
||||||
}
|
}
|
||||||
result = True;
|
result = True;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Entry p = entry;
|
Entry p = entry;
|
||||||
entry = entry->next;
|
entry = entry->next;
|
||||||
while (entry != NULL) {
|
while (entry != NULL) {
|
||||||
if (hashMap->equal(entry->key, key)) {
|
if (hashMap->equal(entry->key, key)) {
|
||||||
hashMap->size--;
|
hashMap->size--;
|
||||||
p->next = entry->next;
|
p->next = entry->next;
|
||||||
free(entry);
|
free(entry);
|
||||||
result = True;
|
result = True;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
p = entry;
|
p = entry;
|
||||||
entry = entry->next;
|
entry = entry->next;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果空间占用不足一半,则释放多余内存
|
// 如果空间占用不足一半,则释放多余内存
|
||||||
if (result && hashMap->autoAssign && hashMap->size < hashMap->listSize / 2) {
|
if (result && hashMap->autoAssign && hashMap->size < hashMap->listSize / 2) {
|
||||||
resetHashMap(hashMap, hashMap->listSize / 2);
|
resetHashMap(hashMap, hashMap->listSize / 2);
|
||||||
}
|
}
|
||||||
return entryKey;
|
return entryKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 默认的判断键是否存在函数
|
||||||
Boolean defaultExists(HashMap hashMap, let key) {
|
Boolean defaultExists(HashMap hashMap, let key) {
|
||||||
int index = hashMap->hashCode(hashMap, key);
|
int index = hashMap->hashCode(hashMap, key);
|
||||||
Entry entry = &hashMap->list[index];
|
Entry entry = &hashMap->list[index];
|
||||||
if (entry->key == NULL) {
|
if (entry->key == NULL) {
|
||||||
return False;
|
return False;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
while (entry != NULL) {
|
while (entry != NULL) {
|
||||||
if (hashMap->equal(entry->key, key)) {
|
if (hashMap->equal(entry->key, key)) {
|
||||||
return True;
|
return True;
|
||||||
}
|
}
|
||||||
entry = entry->next;
|
entry = entry->next;
|
||||||
}
|
}
|
||||||
return False;
|
return False;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 默认的清空哈希表函数
|
||||||
void defaultClear(HashMap hashMap) {
|
void defaultClear(HashMap hashMap) {
|
||||||
for (int i = 0; i < hashMap->listSize; i++) {
|
for (int i = 0; i < hashMap->listSize; i++) {
|
||||||
// 释放冲突值内存
|
// 释放冲突值内存
|
||||||
Entry entry = hashMap->list[i].next;
|
Entry entry = hashMap->list[i].next;
|
||||||
while (entry != NULL) {
|
while (entry != NULL) {
|
||||||
Entry next = entry->next;
|
Entry next = entry->next;
|
||||||
free(entry);
|
free(entry);
|
||||||
entry = next;
|
entry = next;
|
||||||
}
|
}
|
||||||
hashMap->list[i].next = NULL;
|
hashMap->list[i].next = NULL;
|
||||||
}
|
}
|
||||||
// 释放存储空间
|
// 释放存储空间
|
||||||
free(hashMap->list);
|
free(hashMap->list);
|
||||||
hashMap->list = NULL;
|
hashMap->list = NULL;
|
||||||
hashMap->size = -1;
|
hashMap->size = -1;
|
||||||
hashMap->listSize = 0;
|
hashMap->listSize = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 创建一个哈希表
|
||||||
HashMap createHashMap(HashCode hashCode, Equal equal) {
|
HashMap createHashMap(HashCode hashCode, Equal equal) {
|
||||||
HashMap hashMap = newHashMap();
|
HashMap hashMap = newHashMap();
|
||||||
if (hashMap == NULL) {
|
if (hashMap == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
hashMap->size = 0;
|
hashMap->size = 0;
|
||||||
hashMap->listSize = 8;
|
hashMap->listSize = 8;
|
||||||
hashMap->hashCode = hashCode == NULL ? defaultHashCode : hashCode;
|
hashMap->hashCode = hashCode == NULL ? defaultHashCode : hashCode;
|
||||||
hashMap->equal = equal == NULL ? defaultEqual : equal;
|
hashMap->equal = equal == NULL ? defaultEqual : equal;
|
||||||
hashMap->exists = defaultExists;
|
hashMap->exists = defaultExists;
|
||||||
hashMap->get = defaultGet;
|
hashMap->get = defaultGet;
|
||||||
hashMap->put = defaultPut;
|
hashMap->put = defaultPut;
|
||||||
hashMap->remove = defaultRemove;
|
hashMap->remove = defaultRemove;
|
||||||
hashMap->clear = defaultClear;
|
hashMap->clear = defaultClear;
|
||||||
hashMap->autoAssign = True;
|
hashMap->autoAssign = True;
|
||||||
|
|
||||||
// 起始分配8个内存空间,溢出时会自动扩充
|
// 起始分配8个内存空间,溢出时会自动扩充
|
||||||
hashMap->list = newEntryList(hashMap->listSize);
|
hashMap->list = newEntryList(hashMap->listSize);
|
||||||
if (hashMap->list == NULL) {
|
if (hashMap->list == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
Entry p = hashMap->list;
|
Entry p = hashMap->list;
|
||||||
for (int i = 0; i < hashMap->listSize; i++) {
|
for (int i = 0; i < hashMap->listSize; i++) {
|
||||||
p[i].key = p[i].value = p[i].next = NULL;
|
p[i].key = p[i].value = p[i].next = NULL;
|
||||||
}
|
}
|
||||||
return hashMap;
|
return hashMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 创建一个哈希表迭代器
|
||||||
HashMapIterator createHashMapIterator(HashMap hashMap) {
|
HashMapIterator createHashMapIterator(HashMap hashMap) {
|
||||||
HashMapIterator iterator = newHashMapIterator();
|
HashMapIterator iterator = newHashMapIterator();
|
||||||
if (iterator == NULL) {
|
if (iterator == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
iterator->hashMap = hashMap;
|
iterator->hashMap = hashMap;
|
||||||
iterator->count = 0;
|
iterator->count = 0;
|
||||||
iterator->hashCode = -1;
|
iterator->hashCode = -1;
|
||||||
iterator->entry = NULL;
|
iterator->entry = NULL;
|
||||||
return iterator;
|
return iterator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 判断迭代器是否还有下一个元素
|
||||||
Boolean hasNextHashMapIterator(HashMapIterator iterator) {
|
Boolean hasNextHashMapIterator(HashMapIterator iterator) {
|
||||||
return iterator->count < iterator->hashMap->size ? True : False;
|
return iterator->count < iterator->hashMap->size ? True : False;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取迭代器的下一个元素
|
||||||
HashMapIterator nextHashMapIterator(HashMapIterator iterator) {
|
HashMapIterator nextHashMapIterator(HashMapIterator iterator) {
|
||||||
if (hasNextHashMapIterator(iterator)) {
|
if (hasNextHashMapIterator(iterator)) {
|
||||||
if (iterator->entry != NULL && iterator->entry->next != NULL) {
|
if (iterator->entry != NULL && iterator->entry->next != NULL) {
|
||||||
iterator->count++;
|
iterator->count++;
|
||||||
iterator->entry = iterator->entry->next;
|
iterator->entry = iterator->entry->next;
|
||||||
return iterator;
|
return iterator;
|
||||||
}
|
}
|
||||||
while (++iterator->hashCode < iterator->hashMap->listSize) {
|
while (++iterator->hashCode < iterator->hashMap->listSize) {
|
||||||
Entry entry = &iterator->hashMap->list[iterator->hashCode];
|
Entry entry = &iterator->hashMap->list[iterator->hashCode];
|
||||||
if (entry->key != NULL) {
|
if (entry->key != NULL) {
|
||||||
iterator->count++;
|
iterator->count++;
|
||||||
iterator->entry = entry;
|
iterator->entry = entry;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return iterator;
|
return iterator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 释放哈希表迭代器
|
||||||
void freeHashMapIterator(HashMapIterator * iterator) {
|
void freeHashMapIterator(HashMapIterator * iterator) {
|
||||||
free(*iterator);
|
free(*iterator);
|
||||||
*iterator = NULL;
|
*iterator = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 定义简化的宏,用于方便操作哈希表
|
||||||
|
|
||||||
#define Put(map, key, value) map->put(map, (void *)key, (void *)value);
|
#define Put(map, key, value) map->put(map, (void *)key, (void *)value);
|
||||||
#define Get(map, key) (char *)map->get(map, (void *)key)
|
#define Get(map, key) (char *)map->get(map, (void *)key)
|
||||||
#define Remove(map, key) map->remove(map, (void *)key)
|
#define Remove(map, key) map->remove(map, (void *)key)
|
||||||
|
|
Loading…
Reference in New Issue