firstcommit
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 114 KiB |
Before Width: | Height: | Size: 102 KiB After Width: | Height: | Size: 130 KiB |
Before Width: | Height: | Size: 94 KiB After Width: | Height: | Size: 80 KiB |
Before Width: | Height: | Size: 95 KiB After Width: | Height: | Size: 382 KiB |
|
@ -1,323 +1,328 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "test_hash.h" // 包含头文件
|
||||||
|
|
||||||
/**
|
// 声明 resizeHashMap 函数
|
||||||
* @file: test_hash.c
|
void resizeHashMap(struct hashMap* map, int newSize);
|
||||||
* @brief: a application of test hash function
|
|
||||||
* @version: 3.0
|
|
||||||
* @author: Yao wenying
|
|
||||||
* @date: 2023/05/26
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <transform.h>
|
// 修改后的哈希函数,根据键的最后一位数字生成哈希码
|
||||||
#include"test_hash.h"
|
unsigned int defaultHashCode(const void* key) {
|
||||||
|
unsigned int hash = 0;
|
||||||
|
const char* str = (const char*)key;
|
||||||
|
|
||||||
int defaultHashCode(HashMap hashMap, let key) {
|
// 找到字符串的最后一个字符
|
||||||
char * k = (char *)key;
|
while (*str) {
|
||||||
unsigned long h = 0;
|
hash = *str - '0'; // 将最后一位数字转换为整数并赋予哈希码
|
||||||
while (*k) {
|
str++;
|
||||||
h = (h << 4) + *k++;
|
|
||||||
unsigned long g = h & 0xF0000000L;
|
|
||||||
if (g) {
|
|
||||||
h ^= g >> 24;
|
|
||||||
}
|
|
||||||
h &= ~g;
|
|
||||||
}
|
|
||||||
return h % hashMap->listSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
Boolean defaultEqual(let key1, let key2) {
|
|
||||||
return strcmp((string)key1, (string)key2) ? False : True;
|
|
||||||
}
|
|
||||||
|
|
||||||
void resetHashMap(HashMap hashMap, int listSize) {
|
|
||||||
|
|
||||||
if (listSize < 8) return;
|
|
||||||
|
|
||||||
// 键值对临时存储空间
|
|
||||||
Entry tempList = newEntryList(hashMap->size);
|
|
||||||
|
|
||||||
HashMapIterator iterator = createHashMapIterator(hashMap);
|
|
||||||
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);
|
|
||||||
|
|
||||||
// 清除原有键值对数据
|
|
||||||
hashMap->size = 0;
|
|
||||||
for (int i = 0; i < hashMap->listSize; i++) {
|
|
||||||
Entry current = &hashMap->list[i];
|
|
||||||
current->key = NULL;
|
|
||||||
current->value = NULL;
|
|
||||||
if (current->next != NULL) {
|
|
||||||
while (current->next != NULL) {
|
|
||||||
Entry temp = current->next->next;
|
|
||||||
free(current->next);
|
|
||||||
current->next = temp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更改内存大小
|
|
||||||
hashMap->listSize = listSize;
|
|
||||||
Entry relist = (Entry)realloc(hashMap->list, hashMap->listSize * sizeof(struct entry));
|
|
||||||
if (relist != NULL) {
|
|
||||||
hashMap->list = relist;
|
|
||||||
relist = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 初始化数据
|
|
||||||
for (int i = 0; i < hashMap->listSize; i++) {
|
|
||||||
hashMap->list[i].key = NULL;
|
|
||||||
hashMap->list[i].value = NULL;
|
|
||||||
hashMap->list[i].next = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 将所有键值对重新写入内存
|
|
||||||
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) {
|
|
||||||
// 获取哈希值
|
|
||||||
int index = hashMap->hashCode(hashMap, key);
|
|
||||||
|
|
||||||
if (hashMap->list[index].key == NULL) {
|
|
||||||
hashMap->size++;
|
|
||||||
// 该地址为空时直接存储
|
|
||||||
hashMap->list[index].key = key;
|
|
||||||
hashMap->list[index].value = value;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
|
|
||||||
Entry current = &hashMap->list[index];
|
|
||||||
while (current != NULL) {
|
|
||||||
if (hashMap->equal(key, current->key)) {
|
|
||||||
// 对于键值已经存在的直接覆盖
|
|
||||||
current->value = value;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
current = current->next;
|
|
||||||
};
|
|
||||||
|
|
||||||
// 发生冲突则创建节点挂到相应位置的next上
|
|
||||||
Entry entry = newEntry();
|
|
||||||
entry->key = key;
|
|
||||||
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) {
|
|
||||||
if (hashMap->exists(hashMap, key)) {
|
|
||||||
int index = hashMap->hashCode(hashMap, key);
|
|
||||||
Entry entry = &hashMap->list[index];
|
|
||||||
while (entry != NULL) {
|
|
||||||
if (hashMap->equal(entry->key, key)) {
|
|
||||||
return entry->value;
|
|
||||||
}
|
|
||||||
entry = entry->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
let defaultRemove(HashMap hashMap, let key) {
|
|
||||||
int index = hashMap->hashCode(hashMap, key);
|
|
||||||
Entry entry = &hashMap->list[index];
|
|
||||||
if (entry->key == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
let entryKey = entry->key;
|
|
||||||
Boolean result = False;
|
|
||||||
if (hashMap->equal(entry->key, key)) {
|
|
||||||
hashMap->size--;
|
|
||||||
if (entry->next != NULL) {
|
|
||||||
Entry temp = entry->next;
|
|
||||||
entry->key = temp->key;
|
|
||||||
entry->value = temp->value;
|
|
||||||
entry->next = temp->next;
|
|
||||||
free(temp);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
entry->key = NULL;
|
|
||||||
entry->value = NULL;
|
|
||||||
}
|
|
||||||
result = True;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Entry p = entry;
|
|
||||||
entry = entry->next;
|
|
||||||
while (entry != NULL) {
|
|
||||||
if (hashMap->equal(entry->key, key)) {
|
|
||||||
hashMap->size--;
|
|
||||||
p->next = entry->next;
|
|
||||||
free(entry);
|
|
||||||
result = True;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
p = entry;
|
|
||||||
entry = entry->next;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果空间占用不足一半,则释放多余内存
|
|
||||||
if (result && hashMap->autoAssign && hashMap->size < hashMap->listSize / 2) {
|
|
||||||
resetHashMap(hashMap, hashMap->listSize / 2);
|
|
||||||
}
|
|
||||||
return entryKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
Boolean defaultExists(HashMap hashMap, let key) {
|
|
||||||
int index = hashMap->hashCode(hashMap, key);
|
|
||||||
Entry entry = &hashMap->list[index];
|
|
||||||
if (entry->key == NULL) {
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
while (entry != NULL) {
|
|
||||||
if (hashMap->equal(entry->key, key)) {
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
entry = entry->next;
|
|
||||||
}
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void defaultClear(HashMap hashMap) {
|
|
||||||
for (int i = 0; i < hashMap->listSize; i++) {
|
|
||||||
// 释放冲突值内存
|
|
||||||
Entry entry = hashMap->list[i].next;
|
|
||||||
while (entry != NULL) {
|
|
||||||
Entry next = entry->next;
|
|
||||||
free(entry);
|
|
||||||
entry = next;
|
|
||||||
}
|
|
||||||
hashMap->list[i].next = NULL;
|
|
||||||
}
|
|
||||||
// 释放存储空间
|
|
||||||
free(hashMap->list);
|
|
||||||
hashMap->list = NULL;
|
|
||||||
hashMap->size = -1;
|
|
||||||
hashMap->listSize = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
HashMap createHashMap(HashCode hashCode, Equal equal) {
|
|
||||||
HashMap hashMap = newHashMap();
|
|
||||||
if (hashMap == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
hashMap->size = 0;
|
|
||||||
hashMap->listSize = 8;
|
|
||||||
hashMap->hashCode = hashCode == NULL ? defaultHashCode : hashCode;
|
|
||||||
hashMap->equal = equal == NULL ? defaultEqual : equal;
|
|
||||||
hashMap->exists = defaultExists;
|
|
||||||
hashMap->get = defaultGet;
|
|
||||||
hashMap->put = defaultPut;
|
|
||||||
hashMap->remove = defaultRemove;
|
|
||||||
hashMap->clear = defaultClear;
|
|
||||||
hashMap->autoAssign = True;
|
|
||||||
|
|
||||||
// 起始分配8个内存空间,溢出时会自动扩充
|
|
||||||
hashMap->list = newEntryList(hashMap->listSize);
|
|
||||||
if (hashMap->list == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
Entry p = hashMap->list;
|
|
||||||
for (int i = 0; i < hashMap->listSize; i++) {
|
|
||||||
p[i].key = p[i].value = p[i].next = NULL;
|
|
||||||
}
|
|
||||||
return hashMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
HashMapIterator createHashMapIterator(HashMap hashMap) {
|
|
||||||
HashMapIterator iterator = newHashMapIterator();
|
|
||||||
if (iterator == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
iterator->hashMap = hashMap;
|
|
||||||
iterator->count = 0;
|
|
||||||
iterator->hashCode = -1;
|
|
||||||
iterator->entry = NULL;
|
|
||||||
return iterator;
|
|
||||||
}
|
|
||||||
|
|
||||||
Boolean hasNextHashMapIterator(HashMapIterator iterator) {
|
|
||||||
return iterator->count < iterator->hashMap->size ? True : False;
|
|
||||||
}
|
|
||||||
|
|
||||||
HashMapIterator nextHashMapIterator(HashMapIterator iterator) {
|
|
||||||
if (hasNextHashMapIterator(iterator)) {
|
|
||||||
if (iterator->entry != NULL && iterator->entry->next != NULL) {
|
|
||||||
iterator->count++;
|
|
||||||
iterator->entry = iterator->entry->next;
|
|
||||||
return iterator;
|
|
||||||
}
|
|
||||||
while (++iterator->hashCode < iterator->hashMap->listSize) {
|
|
||||||
Entry entry = &iterator->hashMap->list[iterator->hashCode];
|
|
||||||
if (entry->key != NULL) {
|
|
||||||
iterator->count++;
|
|
||||||
iterator->entry = entry;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return iterator;
|
|
||||||
}
|
|
||||||
|
|
||||||
void freeHashMapIterator(HashMapIterator * iterator) {
|
|
||||||
free(*iterator);
|
|
||||||
*iterator = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define Put(map, key, value) map->put(map, (void *)key, (void *)value);
|
|
||||||
#define Get(map, key) (char *)map->get(map, (void *)key)
|
|
||||||
#define Remove(map, key) map->remove(map, (void *)key)
|
|
||||||
#define Existe(map, key) map->exists(map, (void *)key)
|
|
||||||
|
|
||||||
void TestHash() {
|
|
||||||
HashMap map = createHashMap(NULL, NULL);
|
|
||||||
Put(map, "000123", "Annie");
|
|
||||||
Put(map, "000245", "Bob");
|
|
||||||
Put(map, "000284", "Daniel");
|
|
||||||
Put(map, "000281", "Luna");
|
|
||||||
Put(map, "000587", "Yao");
|
|
||||||
Put(map, "000985", "Li Ming");
|
|
||||||
Put(map, "000852", "Janne");
|
|
||||||
|
|
||||||
printf("print the key-values in hashmap:\n");
|
|
||||||
HashMapIterator iterator = createHashMapIterator(map);
|
|
||||||
while (hasNextHashMapIterator(iterator)) {
|
|
||||||
iterator = nextHashMapIterator(iterator);
|
|
||||||
printf("{ key: %s, key: %s, hashcode: %d }\n",
|
|
||||||
(char *)iterator->entry->key, (char *)iterator->entry->value, iterator->hashCode);
|
|
||||||
}
|
}
|
||||||
printf("key: 000852, exists: %s\n", Existe(map, "000852") ? "true" : "false");
|
|
||||||
printf("000852: %s\n", Get(map, "000852"));
|
|
||||||
printf("remove 000852 %s\n", Remove(map, "000852") ? "true" : "false");
|
|
||||||
printf("key: 000852, exists: %s\n", Existe(map, "000852") ? "true" : "false");
|
|
||||||
|
|
||||||
map->clear(map);
|
return hash;
|
||||||
freeHashMapIterator(&iterator);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 默认判等函数,适用于字符串键
|
||||||
|
int defaultEqual(const void* key1, const void* key2) {
|
||||||
|
return strcmp((const char*)key1, (const char*)key2) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 默认清空Map函数
|
||||||
|
void defaultClear(HashMap map) {
|
||||||
|
if (map == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 释放每个键值对链表
|
||||||
|
for (int i = 0; i < map->listSize; i++) {
|
||||||
|
Entry entry = map->list[i];
|
||||||
|
while (entry != NULL) {
|
||||||
|
Entry temp = entry;
|
||||||
|
entry = entry->next;
|
||||||
|
free(temp);
|
||||||
|
}
|
||||||
|
map->list[i] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
map->size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 默认添加键值对函数
|
||||||
|
// 修改 defaultPut 函数来处理哈希冲突
|
||||||
|
void defaultPut(HashMap map, const void* key, const void* value) {
|
||||||
|
if (map == NULL || key == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算哈希值
|
||||||
|
unsigned int index = map->hashCode(key) % map->listSize;
|
||||||
|
|
||||||
|
// 查找是否已经存在相同的键
|
||||||
|
Entry entry = map->list[index];
|
||||||
|
Entry prev = NULL;
|
||||||
|
while (entry != NULL) {
|
||||||
|
if (map->equal(entry->key, key)) {
|
||||||
|
// 如果找到相同的键,更新值并返回
|
||||||
|
entry->value = value;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
prev = entry;
|
||||||
|
entry = entry->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建新的键值对
|
||||||
|
Entry newEntry = (Entry)malloc(sizeof(struct entry));
|
||||||
|
if (newEntry == NULL) {
|
||||||
|
fprintf(stderr, "内存分配失败\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
newEntry->key = key;
|
||||||
|
newEntry->value = value;
|
||||||
|
newEntry->next = NULL;
|
||||||
|
|
||||||
|
// 如果链表为空,直接插入
|
||||||
|
if (prev == NULL) {
|
||||||
|
map->list[index] = newEntry;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// 否则将新节点链接到链表末尾
|
||||||
|
prev->next = newEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
map->size++;
|
||||||
|
|
||||||
|
// 如果需要自动扩容
|
||||||
|
if (map->autoAssign && map->size >= map->listSize) {
|
||||||
|
resizeHashMap(map, map->listSize * 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 默认获取键对应值函数
|
||||||
|
const void* defaultGet(HashMap map, const void* key) {
|
||||||
|
if (map == NULL || key == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算哈希值
|
||||||
|
unsigned int index = map->hashCode(key) % map->listSize;
|
||||||
|
|
||||||
|
// 查找键值对
|
||||||
|
Entry entry = map->list[index];
|
||||||
|
while (entry != NULL) {
|
||||||
|
if (map->equal(entry->key, key)) {
|
||||||
|
return entry->value;
|
||||||
|
}
|
||||||
|
entry = entry->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL; // 键不存在
|
||||||
|
}
|
||||||
|
|
||||||
|
// 默认删除键值对函数
|
||||||
|
void defaultRemove(HashMap map, const void* key) {
|
||||||
|
if (map == NULL || key == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算哈希值
|
||||||
|
unsigned int index = map->hashCode(key) % map->listSize;
|
||||||
|
|
||||||
|
// 查找并删除键值对
|
||||||
|
Entry entry = map->list[index];
|
||||||
|
Entry prev = NULL;
|
||||||
|
while (entry != NULL) {
|
||||||
|
if (map->equal(entry->key, key)) {
|
||||||
|
if (prev != NULL) {
|
||||||
|
prev->next = entry->next;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
map->list[index] = entry->next;
|
||||||
|
}
|
||||||
|
free(entry);
|
||||||
|
map->size--;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
prev = entry;
|
||||||
|
entry = entry->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 默认判断键是否存在函数
|
||||||
|
int defaultExists(HashMap map, const void* key) {
|
||||||
|
if (map == NULL || key == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算哈希值
|
||||||
|
unsigned int index = map->hashCode(key) % map->listSize;
|
||||||
|
|
||||||
|
// 查找键值对
|
||||||
|
Entry entry = map->list[index];
|
||||||
|
while (entry != NULL) {
|
||||||
|
if (map->equal(entry->key, key)) {
|
||||||
|
return 1; // 键存在
|
||||||
|
}
|
||||||
|
entry = entry->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0; // 键不存在
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重新构建哈希表,用于动态扩容
|
||||||
|
void resizeHashMap(HashMap map, int newSize) {
|
||||||
|
if (map == NULL || newSize <= map->listSize) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Entry* newList = (Entry*)calloc(newSize, sizeof(Entry));
|
||||||
|
if (newList == NULL) {
|
||||||
|
fprintf(stderr, "内存分配失败\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将原有键值对重新哈希到新的存储区域
|
||||||
|
for (int i = 0; i < map->listSize; i++) {
|
||||||
|
Entry entry = map->list[i];
|
||||||
|
while (entry != NULL) {
|
||||||
|
Entry next = entry->next;
|
||||||
|
unsigned int newIndex = map->hashCode(entry->key) % newSize;
|
||||||
|
entry->next = newList[newIndex];
|
||||||
|
newList[newIndex] = entry;
|
||||||
|
entry = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(map->list);
|
||||||
|
map->list = newList;
|
||||||
|
map->listSize = newSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建一个哈希结构
|
||||||
|
HashMap createHashMap(int initialSize, HashCode hashCode, Equal equal, int autoAssign) {
|
||||||
|
HashMap map = (HashMap)malloc(sizeof(struct hashMap));
|
||||||
|
if (map == NULL) {
|
||||||
|
fprintf(stderr, "内存分配失败\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
map->size = 0;
|
||||||
|
map->listSize = initialSize;
|
||||||
|
map->hashCode = (hashCode != NULL) ? hashCode : defaultHashCode;
|
||||||
|
map->equal = (equal != NULL) ? equal : defaultEqual;
|
||||||
|
map->list = (Entry*)calloc(initialSize, sizeof(Entry));
|
||||||
|
map->put = defaultPut; // 初始化为 defaultPut 函数
|
||||||
|
map->get = defaultGet; // 初始化为 defaultGet 函数
|
||||||
|
map->remove = defaultRemove; // 初始化为 defaultRemove 函数
|
||||||
|
map->clear = defaultClear; // 初始化为 defaultClear 函数
|
||||||
|
map->exists = defaultExists; // 初始化为 defaultExists 函数
|
||||||
|
map->autoAssign = autoAssign;
|
||||||
|
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 示例函数,用于测试链地址法解决哈希冲突
|
||||||
|
void TestHash() {
|
||||||
|
// 创建哈希结构
|
||||||
|
HashMap map = createHashMap(10, defaultHashCode, defaultEqual, 1);
|
||||||
|
|
||||||
|
printf("创建哈希结构\n");
|
||||||
|
|
||||||
|
// 添加键值对
|
||||||
|
const char* no1 = "20414";
|
||||||
|
const char* name1 = "Shi Tou";
|
||||||
|
printf("添加键值对 - Key: %s, Value: %s\n", no1, name1);
|
||||||
|
map->put(map, no1, name1);
|
||||||
|
|
||||||
|
const char* no2 = "20237";
|
||||||
|
const char* name2 = "Wang Le";
|
||||||
|
printf("添加键值对 - Key: %s, Value: %s\n", no2, name2);
|
||||||
|
map->put(map, no2, name2);
|
||||||
|
|
||||||
|
const char* no3 = "19385";
|
||||||
|
const char* name3 = "Zhong Jun";
|
||||||
|
printf("添加键值对 - Key: %s, Value: %s\n", no3, name3);
|
||||||
|
map->put(map, no3, name3);
|
||||||
|
|
||||||
|
const char* no4 = "24378";
|
||||||
|
const char* name4 = "fu rui";
|
||||||
|
printf("添加键值对 - Key: %s, Value: %s\n", no4, name4);
|
||||||
|
map->put(map, no4, name4);
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
// 输出所有键值对和相应的 hashcode
|
||||||
|
printf("输出所有键值对和相应的 hashcode\n");
|
||||||
|
for (int i = 0; i < map->listSize; i++) {
|
||||||
|
Entry entry = map->list[i];
|
||||||
|
while (entry != NULL) {
|
||||||
|
printf("Key: %s, Value: %s, HashCode: %u\n", (const char*)entry->key, (const char*)entry->value, map->hashCode(entry->key));
|
||||||
|
entry = entry->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
// 获取键对应值
|
||||||
|
printf("获取键对应值 - Key: %s\n", no1);
|
||||||
|
const char* name = (const char*)map->get(map, no1);
|
||||||
|
if (name != NULL) {
|
||||||
|
printf("%s is %s\n", no1, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
// 判断键是否存在
|
||||||
|
printf("判断键是否存在 - Key: %s\n", no2);
|
||||||
|
if (map->exists(map, no2)) {
|
||||||
|
printf("%s 存在\n", no2);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf("%s 不存在\n", no2);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
// 删除键值对
|
||||||
|
printf("删除键值对 - Key: %s\n", no2);
|
||||||
|
map->remove(map, no2);
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
// 判断键是否存在
|
||||||
|
printf("判断键是否存在 - Key: %s\n", no2);
|
||||||
|
if (map->exists(map, no2)) {
|
||||||
|
printf("%s 存在\n", no2);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf("%s 不存在\n", no2);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
// 添加具有相同哈希值的键值对,模拟哈希冲突
|
||||||
|
const char* no5 = "20425";
|
||||||
|
const char* name5 = "xiao chen";
|
||||||
|
printf("添加键值对 - Key: %s, Value: %s (哈希冲突)\n", no5, name5);
|
||||||
|
map->put(map, no5, name5);
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
// 输出所有键值对和相应的 hashcode
|
||||||
|
printf("输出所有键值对和相应的 hashcode(包括哈希冲突)\n");
|
||||||
|
for (int i = 0; i < map->listSize; i++) {
|
||||||
|
Entry entry = map->list[i];
|
||||||
|
while (entry != NULL) {
|
||||||
|
printf("Key: %s, Value: %s, HashCode: %u\n", (const char*)entry->key, (const char*)entry->value, map->hashCode(entry->key));
|
||||||
|
entry = entry->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清空 Map
|
||||||
|
map->clear(map);
|
||||||
|
|
||||||
|
// 释放哈希结构
|
||||||
|
free(map->list);
|
||||||
|
free(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
PRIV_SHELL_CMD_FUNCTION(TestHash, Implement hash_map, PRIV_SHELL_CMD_MAIN_ATTR);
|
PRIV_SHELL_CMD_FUNCTION(TestHash, Implement hash_map, PRIV_SHELL_CMD_MAIN_ATTR);
|
|
@ -1,129 +1,34 @@
|
||||||
|
#ifndef TEST_HASH_H
|
||||||
|
#define TEST_HASH_H
|
||||||
|
|
||||||
/**
|
// 键值对结构
|
||||||
* @file: test_hash.h
|
|
||||||
* @brief: a application of test hash function
|
|
||||||
* @version: 3.0
|
|
||||||
* @author: Yao wenying
|
|
||||||
* @date: 2023/05/26
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef __HASHMAP_H__
|
|
||||||
#define __HASHMAP_H__
|
|
||||||
|
|
||||||
#include<stdlib.h>
|
|
||||||
#include<string.h>
|
|
||||||
#include<stdio.h>
|
|
||||||
|
|
||||||
|
|
||||||
// 实现数据的基本类型
|
|
||||||
// 字符串类型
|
|
||||||
#define string char *
|
|
||||||
#define newString(str) strcpy((char *)malloc(strlen(str) + 1), str)
|
|
||||||
#define NEW(type) (type *)malloc(sizeof(type))
|
|
||||||
|
|
||||||
// 布尔类型
|
|
||||||
enum _Boolean { True = 1, False = 0 };
|
|
||||||
typedef enum _Boolean Boolean;
|
|
||||||
|
|
||||||
#define let void *
|
|
||||||
|
|
||||||
typedef struct entry {
|
typedef struct entry {
|
||||||
let key; // 键
|
const void* key;
|
||||||
let value; // 值
|
const void* value;
|
||||||
struct entry * next; // 冲突链表
|
struct entry* next;
|
||||||
}*Entry;
|
} *Entry;
|
||||||
|
|
||||||
#define newEntry() NEW(struct entry)
|
// 哈希函数的类型定义
|
||||||
#define newEntryList(length) (Entry)malloc(length * sizeof(struct entry))
|
typedef unsigned int (*HashCode)(const void* key);
|
||||||
|
|
||||||
|
// 判断两个键是否相等的函数类型定义
|
||||||
|
typedef int (*Equal)(const void* key1, const void* key2);
|
||||||
|
|
||||||
// 哈希结构
|
// 哈希结构
|
||||||
typedef struct hashMap *HashMap;
|
|
||||||
|
|
||||||
#define newHashMap() NEW(struct hashMap)
|
|
||||||
|
|
||||||
// 哈希函数类型
|
|
||||||
typedef int(*HashCode)(HashMap, let key);
|
|
||||||
|
|
||||||
// 判等函数类型
|
|
||||||
typedef Boolean(*Equal)(let key1, let key2);
|
|
||||||
|
|
||||||
// 添加键函数类型
|
|
||||||
typedef void(*Put)(HashMap hashMap, let key, let value);
|
|
||||||
|
|
||||||
// 获取键对应值的函数类型
|
|
||||||
typedef let(*Get)(HashMap hashMap, let key);
|
|
||||||
|
|
||||||
// 删除键的函数类型
|
|
||||||
typedef let(*Remove)(HashMap hashMap, let key);
|
|
||||||
|
|
||||||
// 清空Map的函数类型
|
|
||||||
typedef void(*Clear)(HashMap hashMap);
|
|
||||||
|
|
||||||
// 判断键值是否存在的函数类型
|
|
||||||
typedef Boolean(*Exists)(HashMap hashMap, let key);
|
|
||||||
|
|
||||||
typedef struct hashMap {
|
typedef struct hashMap {
|
||||||
int size; // 当前大小
|
int size; // 当前大小
|
||||||
int listSize; // 有效空间大小
|
int listSize; // 有效空间大小
|
||||||
HashCode hashCode; // 哈希函数
|
HashCode hashCode; // 哈希函数
|
||||||
Equal equal; // 判等函数
|
Equal equal; // 判等函数
|
||||||
Entry list; // 存储区域
|
Entry* list; // 存储区域
|
||||||
Put put; // 添加键的函数
|
void (*put)(struct hashMap* map, const void* key, const void* value); // 添加键的函数
|
||||||
Get get; // 获取键对应值的函数
|
const void* (*get)(struct hashMap* map, const void* key); // 获取键对应值的函数
|
||||||
Remove remove; // 删除键
|
void (*remove)(struct hashMap* map, const void* key); // 删除键
|
||||||
Clear clear; // 清空Map
|
void (*clear)(struct hashMap* map); // 清空Map
|
||||||
Exists exists; // 判断键是否存在
|
int (*exists)(struct hashMap* map, const void* key); // 判断键是否存在
|
||||||
Boolean autoAssign; // 设定是否根据当前数据量动态调整内存大小,默认开启
|
int autoAssign; // 是否根据当前数据量动态调整内存大小,默认开启
|
||||||
}*HashMap;
|
} *HashMap;
|
||||||
|
|
||||||
// 迭代器结构
|
// 在此放置函数原型
|
||||||
typedef struct hashMapIterator {
|
|
||||||
Entry entry; // 迭代器当前指向
|
|
||||||
int count; // 迭代次数
|
|
||||||
int hashCode; // 键值对的哈希值
|
|
||||||
HashMap hashMap;
|
|
||||||
}*HashMapIterator;
|
|
||||||
|
|
||||||
#define newHashMapIterator() NEW(struct hashMapIterator)
|
#endif /* TEST_HASH_H */
|
||||||
|
|
||||||
// 默认哈希函数
|
|
||||||
static int defaultHashCode(HashMap hashMap, let key);
|
|
||||||
|
|
||||||
// 默认判断键值是否相等
|
|
||||||
static Boolean defaultEqual(let key1, let key2);
|
|
||||||
|
|
||||||
// 默认添加键值对
|
|
||||||
static void defaultPut(HashMap hashMap, let key, let value);
|
|
||||||
|
|
||||||
// 默认获取键对应值
|
|
||||||
static let defaultGet(HashMap hashMap, let key);
|
|
||||||
|
|
||||||
// 默认删除键
|
|
||||||
static let defaultRemove(HashMap hashMap, let key);
|
|
||||||
|
|
||||||
// 默认判断键是否存在
|
|
||||||
static Boolean defaultExists(HashMap hashMap, let key);
|
|
||||||
|
|
||||||
// 默认清空Map
|
|
||||||
static void defaultClear(HashMap hashMap);
|
|
||||||
|
|
||||||
// 重新构建
|
|
||||||
static void resetHashMap(HashMap hashMap, int listSize);
|
|
||||||
|
|
||||||
// 创建一个哈希结构
|
|
||||||
HashMap createHashMap(HashCode hashCode, Equal equal);
|
|
||||||
|
|
||||||
// 创建哈希结构迭代器
|
|
||||||
HashMapIterator createHashMapIterator(HashMap hashMap);
|
|
||||||
|
|
||||||
// 迭代器是否有下一个
|
|
||||||
Boolean hasNextHashMapIterator(HashMapIterator iterator);
|
|
||||||
|
|
||||||
// 迭代到下一次
|
|
||||||
HashMapIterator nextHashMapIterator(HashMapIterator iterator);
|
|
||||||
|
|
||||||
// 释放迭代器内存
|
|
||||||
void freeHashMapIterator(HashMapIterator * iterator);
|
|
||||||
|
|
||||||
#endif // !__HASHMAP_H__
|
|
||||||
|
|