warmup_1st_issue1
|
@ -1,10 +1,10 @@
|
|||
menu "test app"
|
||||
menuconfig USER_TEST
|
||||
config USER_TEST
|
||||
bool "Enable application test function "
|
||||
default n
|
||||
|
||||
if USER_TEST
|
||||
menuconfig USER_TEST_ADC
|
||||
config USER_TEST_ADC
|
||||
bool "Config test adc"
|
||||
default n
|
||||
if USER_TEST_ADC
|
||||
|
@ -15,7 +15,7 @@ menu "test app"
|
|||
endif
|
||||
endif
|
||||
|
||||
menuconfig USER_TEST_DAC
|
||||
config USER_TEST_DAC
|
||||
bool "Config test dac"
|
||||
default n
|
||||
if USER_TEST_DAC
|
||||
|
@ -26,7 +26,7 @@ menu "test app"
|
|||
endif
|
||||
endif
|
||||
|
||||
menuconfig USER_TEST_FS
|
||||
config USER_TEST_FS
|
||||
bool "Config test fs with sd or usb"
|
||||
default n
|
||||
if USER_TEST_FS
|
||||
|
@ -38,7 +38,7 @@ menu "test app"
|
|||
endif
|
||||
|
||||
|
||||
menuconfig USER_TEST_GPIO
|
||||
config USER_TEST_GPIO
|
||||
select BSP_USING_GPIO
|
||||
select RESOURCES_PIN
|
||||
select BSP_USING_LED
|
||||
|
@ -53,7 +53,7 @@ menu "test app"
|
|||
endif
|
||||
endif
|
||||
|
||||
menuconfig USER_TEST_LORA
|
||||
config USER_TEST_LORA
|
||||
select BSP_USING_UART
|
||||
select BSP_USING_GPIO
|
||||
select RESOURCES_PIN
|
||||
|
@ -72,7 +72,7 @@ menu "test app"
|
|||
endif
|
||||
endif
|
||||
|
||||
menuconfig USER_TEST_RS485
|
||||
config USER_TEST_RS485
|
||||
select BSP_USING_UART
|
||||
select BSP_USING_GPIO
|
||||
select RESOURCES_PIN
|
||||
|
@ -90,7 +90,7 @@ menu "test app"
|
|||
endif
|
||||
endif
|
||||
|
||||
menuconfig USER_TEST_RTC
|
||||
config USER_TEST_RTC
|
||||
select BSP_USING_RTC
|
||||
bool "Config test rtc"
|
||||
default n
|
||||
|
@ -102,7 +102,7 @@ menu "test app"
|
|||
endif
|
||||
endif
|
||||
|
||||
menuconfig USER_TEST_HWTIMER
|
||||
config USER_TEST_HWTIMER
|
||||
select BSP_USING_HWTIMER
|
||||
select BSP_USING_GPIO
|
||||
select RESOURCES_PIN
|
||||
|
@ -120,7 +120,7 @@ menu "test app"
|
|||
endif
|
||||
endif
|
||||
|
||||
menuconfig USER_TEST_WDT
|
||||
config USER_TEST_WDT
|
||||
select BSP_USING_WDT0
|
||||
bool "Config test watchdog"
|
||||
default n
|
||||
|
@ -132,7 +132,7 @@ menu "test app"
|
|||
endif
|
||||
endif
|
||||
|
||||
menuconfig USER_TEST_LCD_EDU
|
||||
config USER_TEST_LCD_EDU
|
||||
select BSP_USING_LCD
|
||||
bool "Config test lcd in PrivOpen"
|
||||
default n
|
||||
|
@ -144,7 +144,7 @@ menu "test app"
|
|||
endif
|
||||
endif
|
||||
|
||||
menuconfig USER_TEST_TOUCH
|
||||
config USER_TEST_TOUCH
|
||||
select BSP_USING_TOUCH
|
||||
bool "Config test touch"
|
||||
default n
|
||||
|
@ -159,7 +159,7 @@ menu "test app"
|
|||
endif
|
||||
endif
|
||||
|
||||
menuconfig USER_TEST_I2C
|
||||
config USER_TEST_I2C
|
||||
select BSP_USING_I2C
|
||||
bool "Config test i2c"
|
||||
default n
|
||||
|
@ -171,7 +171,7 @@ menu "test app"
|
|||
endif
|
||||
endif
|
||||
|
||||
menuconfig USER_TEST_CAN
|
||||
config USER_TEST_CAN
|
||||
select BSP_USING_CAN
|
||||
bool "Config test can"
|
||||
default n
|
||||
|
@ -183,7 +183,7 @@ menu "test app"
|
|||
endif
|
||||
endif
|
||||
|
||||
menuconfig USER_TEST_CAMERA
|
||||
config USER_TEST_CAMERA
|
||||
select BSP_USING_CAMERA
|
||||
select BSP_USING_LCD
|
||||
bool "Config test camera with lcd"
|
||||
|
@ -207,7 +207,7 @@ menu "test app"
|
|||
bool "Config test lcd device"
|
||||
default n
|
||||
|
||||
menuconfig USER_TEST_ETHERNET
|
||||
config USER_TEST_ETHERNET
|
||||
bool "Config test ethernet only for edu-riscv64"
|
||||
default n
|
||||
if USER_TEST_ETHERNET
|
||||
|
@ -225,7 +225,7 @@ menu "test app"
|
|||
endif
|
||||
endif
|
||||
|
||||
menuconfig USER_TEST_FLASH
|
||||
config USER_TEST_FLASH
|
||||
bool "Config test w25q128 device"
|
||||
default n
|
||||
if USER_TEST_FLASH
|
||||
|
@ -236,47 +236,47 @@ menu "test app"
|
|||
endif
|
||||
endif
|
||||
|
||||
menuconfig USER_TEST_TIMER
|
||||
config USER_TEST_TIMER
|
||||
bool "Config test soft timer"
|
||||
default n
|
||||
|
||||
menuconfig USER_TEST_HASH
|
||||
config USER_TEST_HASH
|
||||
bool "Config test hash"
|
||||
default n
|
||||
|
||||
menuconfig USER_TEST_RADIX
|
||||
config USER_TEST_RADIX
|
||||
bool "Config test radix tree"
|
||||
default n
|
||||
|
||||
menuconfig USER_TEST_RBTREE
|
||||
config USER_TEST_RBTREE
|
||||
bool "Config test red black tree"
|
||||
default n
|
||||
|
||||
menuconfig USER_TEST_WEBSERVER
|
||||
config USER_TEST_WEBSERVER
|
||||
bool "Config test webserver"
|
||||
default n
|
||||
|
||||
menuconfig USER_TEST_MQTTCLIENT
|
||||
config USER_TEST_MQTTCLIENT
|
||||
bool "Config test mqtt client"
|
||||
default n
|
||||
|
||||
menuconfig USER_TEST_FTPCLIENT
|
||||
config USER_TEST_FTPCLIENT
|
||||
bool "Config test ftp client"
|
||||
default n
|
||||
|
||||
menuconfig USER_TEST_LORA_P2P
|
||||
config USER_TEST_LORA_P2P
|
||||
bool "Config test lora p2p"
|
||||
default n
|
||||
|
||||
menuconfig USER_TEST_LORAWAN_SINGLEGW
|
||||
config USER_TEST_LORAWAN_SINGLEGW
|
||||
bool "Config test lorawan single channel gateway"
|
||||
default n
|
||||
|
||||
menuconfig USER_TEST_CANOPEN
|
||||
config USER_TEST_CANOPEN
|
||||
bool "Config test CanOpen"
|
||||
default n
|
||||
|
||||
menuconfig USER_TEST_USB_CAMERA
|
||||
config USER_TEST_USB_CAMERA
|
||||
bool "Config test usb camera"
|
||||
default n
|
||||
|
||||
|
|
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 218 KiB |
Before Width: | Height: | Size: 102 KiB |
After Width: | Height: | Size: 213 KiB |
|
@ -1,58 +1,58 @@
|
|||
# 基于cortex-m3-emulator实现哈希表并测试验证##
|
||||
|
||||
## 1. 简介
|
||||
利用c语言实现了哈希表(HashMap),包括添加键值对(Put),获取键对应的值(Get), 删除健(Delete),清空哈希表(Clear), 迭代遍历哈希表(hashMapIterator)等功能
|
||||
操作。
|
||||
|
||||
利用数组(Entry)作为存储空间,利用链表(*next)解决冲突。当哈希表的大小超过数组大小后,为避免发生冲突过多的情况,可以对哈希表扩容。
|
||||
利用C语言实现了哈希表(HashTable),使用链地址法解决冲突问题。可执行的操作包括添加结点,获取元素的Hash值,删除结点,清空哈希表,打印哈希表。
|
||||
|
||||
定义结点类型为CharList,用数组和链表存储元素。当发生冲突时利用链表的next指针访问尾结点并插入元素,删除结点采用后插法。
|
||||
|
||||
## 2. 数据结构设计说明
|
||||
键值对结构
|
||||
typedef struct entry {
|
||||
void * key; // 键
|
||||
void * value; // 值
|
||||
struct entry * next; // 冲突链表
|
||||
}*Entry;
|
||||
元素结点数据结构
|
||||
```c
|
||||
typedef struct CharList{
|
||||
|
||||
哈希结构
|
||||
typedef struct hashMap {
|
||||
int size; // 当前大小
|
||||
int listSize; // 有效空间大小
|
||||
HashCode hashCode; // 哈希函数
|
||||
Equal equal; // 判等函数
|
||||
Entry list; // 存储区域
|
||||
Put put; // 添加键的函数
|
||||
Get get; // 获取键对应值的函数
|
||||
Remove remove; // 删除键
|
||||
Clear clear; // 清空Map
|
||||
Exists exists; // 判断键是否存在
|
||||
Boolean autoAssign; // 设定是否根据当前数据量动态调整内存大小,默认开启
|
||||
}*HashMap;
|
||||
struct CharList* next;
|
||||
char *data;
|
||||
|
||||
}CharList;
|
||||
```
|
||||
|
||||
哈希表数据结构:
|
||||
```c
|
||||
typedef struct HashTable{
|
||||
|
||||
struct CharList **list;
|
||||
int table_size;
|
||||
|
||||
}HashTable;
|
||||
```
|
||||
|
||||
包括以下函数功能,分别为:
|
||||
`createHashMap`:创建一个哈希结构
|
||||
`defaultPut`:添加键值对
|
||||
`defaultGet`:获取键对应值
|
||||
`defaultRemove`:删除指定键的键值对
|
||||
`defaultExists`:判断键值是否存在
|
||||
`defaultClear`:清空Map的函数类型
|
||||
`resetHashMap`:重新构建哈希表
|
||||
|
||||
GetHashCode:获取插入元素的哈希值
|
||||
|
||||
CreateHashTable:创建一个制定大小的空哈希表
|
||||
|
||||
InsertData:插入一个元素
|
||||
|
||||
DeleteData:删除一个元素
|
||||
|
||||
ClearTable:清空哈希表
|
||||
|
||||
|
||||
## 3. 测试程序说明
|
||||
测试了哈希表的插入键值对(Put),判断键是否存在(Exist),获取键对应的值(Get), 删除健(Delete),迭代遍历哈希表(hashMapIterator),清空哈希表(Clear)等操作。
|
||||
并展示了利用链地址法解决哈希冲突的示例, 两个不同的人(Bob和Li Ming)的hashcode相同。
|
||||
测试创建哈希表,插入元素,删除元素,进行相应操作后打印整个哈希表
|
||||
|
||||
并测试了使用链地址法解决冲突问题,哈希值相同的元素被放在同一个链表中
|
||||
|
||||
## 4. 运行结果(##需结合运行测试截图按步骤说明##)
|
||||

|
||||
打开menuconfig之后,将test_hash_map开启(y),保存后退出
|
||||

|
||||
打开menuconfig之后,开启application菜单中的TestHash命令
|
||||
|
||||

|
||||
编译XiZi-cortex-m3-emulator.elf成功
|
||||
|
||||

|
||||
启动qemu模拟Xiuos操作系统,验证TestHash注册Shell命令
|
||||
|
||||

|
||||
执行TestHash命令,打印测试结果。
|
||||

|
||||

|
||||
启动qemu模拟器并执行TestHash命令,打印测试结果。
|
||||
|
||||
|
|
Before Width: | Height: | Size: 94 KiB |
Before Width: | Height: | Size: 95 KiB |
After Width: | Height: | Size: 104 KiB |
After Width: | Height: | Size: 114 KiB |
|
@ -1,323 +1,153 @@
|
|||
|
||||
/**
|
||||
* @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"test_hash.h"
|
||||
|
||||
int defaultHashCode(HashMap hashMap, let key) {
|
||||
char * k = (char *)key;
|
||||
unsigned long h = 0;
|
||||
while (*k) {
|
||||
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);
|
||||
freeHashMapIterator(&iterator);
|
||||
}
|
||||
|
||||
PRIV_SHELL_CMD_FUNCTION(TestHash, Implement hash_map, PRIV_SHELL_CMD_MAIN_ATTR);
|
||||
/*
|
||||
* Copyright (c) 2020 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file: test_hash.c
|
||||
* @brief: a application of hashtable
|
||||
* @version: 1.0
|
||||
* @author: Ambrumf
|
||||
* @date: 2023/9/12
|
||||
*/
|
||||
|
||||
#include"test_hash.h"
|
||||
|
||||
CharList* InitCharList()
|
||||
{
|
||||
CharList *list = (CharList*)malloc(sizeof(CharList));
|
||||
list->next=NULL;
|
||||
return list;
|
||||
}
|
||||
|
||||
HashTable* CreateHashTable(int size)
|
||||
{
|
||||
HashTable *table = (HashTable*)malloc(sizeof(HashTable));
|
||||
table->table_size = size;
|
||||
table->list = (CharList**)malloc(size*sizeof(CharList*));
|
||||
for(int i=0;i<size;i++)table->list[i] = InitCharList();
|
||||
return table;
|
||||
}
|
||||
|
||||
int GetHashCode(char *str,int size)
|
||||
{
|
||||
int base = 0x3f3f3f3f % size;
|
||||
for(int i=0;str[i];i++){
|
||||
base = (base * base + str[i]) % size;
|
||||
}
|
||||
return base;
|
||||
}
|
||||
|
||||
bool FindData(HashTable* table,char *str)
|
||||
{
|
||||
int size=table->table_size;
|
||||
int hash_code=GetHashCode(str,size);
|
||||
CharList *present_node=table->list[hash_code]->next;
|
||||
while(present_node){
|
||||
if(strcmp(present_node->data,str)==0)return true;
|
||||
present_node=present_node->next;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool InsertData(HashTable *table,char *str)
|
||||
{
|
||||
int size=table->table_size;
|
||||
int hash_code=GetHashCode(str,size);
|
||||
bool exist=FindData(table,str);
|
||||
if(exist)return false;
|
||||
CharList *present_node=table->list[hash_code];
|
||||
while(present_node->next){
|
||||
present_node=present_node->next;
|
||||
}
|
||||
present_node->next = malloc(sizeof(CharList));
|
||||
present_node->next->data=malloc(sizeof(str)*(strlen(str)+1));
|
||||
present_node->next->next=NULL;
|
||||
strcpy(present_node->next->data,str);
|
||||
return true;
|
||||
}
|
||||
|
||||
void DeleteList(CharList *list)
|
||||
{
|
||||
CharList *present_node=list;
|
||||
while(present_node){
|
||||
CharList *next_node = present_node->next;
|
||||
free(present_node);
|
||||
present_node = next_node;
|
||||
};
|
||||
}
|
||||
|
||||
bool DeleteData(HashTable *table,char *str)
|
||||
{
|
||||
int size=table->table_size;
|
||||
int hash_code=GetHashCode(str,size);
|
||||
bool exist=FindData(table,str);
|
||||
if(!exist)return false;
|
||||
CharList *previous_node=table->list[hash_code];
|
||||
CharList *present_node=table->list[hash_code]->next;
|
||||
while(present_node && strcmp(present_node->data,str)!=0){
|
||||
previous_node=present_node;
|
||||
present_node=present_node->next;
|
||||
}
|
||||
previous_node->next=present_node->next;
|
||||
free(present_node);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ClearTable(HashTable *table)
|
||||
{
|
||||
int size=table->table_size;
|
||||
for(int i=0;i<size;i++){
|
||||
DeleteList(table->list[i]);
|
||||
}
|
||||
free(table->list);
|
||||
free(table);
|
||||
}
|
||||
|
||||
void ShowTable(HashTable *table)
|
||||
{
|
||||
int size=table->table_size;
|
||||
for(int i=0;i<size;i++){
|
||||
printf("%d ",i);
|
||||
CharList *present_node=table->list[i]->next;
|
||||
while(present_node){
|
||||
printf("%s ",present_node->data);
|
||||
present_node = present_node->next;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void TestHash()
|
||||
{
|
||||
HashTable* table = CreateHashTable(8);
|
||||
printf("创建一个空哈希表,长度为8:\n");
|
||||
ShowTable(table);
|
||||
|
||||
printf("插入元素:\n");
|
||||
InsertData(table,"spring");
|
||||
InsertData(table,"456");
|
||||
InsertData(table,"apple");
|
||||
InsertData(table,"MingLei");
|
||||
InsertData(table,"1e9+7");
|
||||
InsertData(table,"love");
|
||||
InsertData(table,"998244353");
|
||||
InsertData(table,"65535");
|
||||
InsertData(table,"python");
|
||||
ShowTable(table);
|
||||
|
||||
printf("删除元素apple:\n");
|
||||
DeleteData(table,"apple");
|
||||
ShowTable(table);
|
||||
|
||||
ClearTable(table);
|
||||
}
|
||||
PRIV_SHELL_CMD_FUNCTION(TestHash , Implement hashTable,PRIV_SHELL_CMD_MAIN_ATTR);
|
|
@ -1,129 +1,57 @@
|
|||
|
||||
/**
|
||||
* @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 {
|
||||
let key; // 键
|
||||
let value; // 值
|
||||
struct entry * next; // 冲突链表
|
||||
}*Entry;
|
||||
|
||||
#define newEntry() NEW(struct entry)
|
||||
#define newEntryList(length) (Entry)malloc(length * sizeof(struct entry))
|
||||
|
||||
// 哈希结构
|
||||
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 {
|
||||
int size; // 当前大小
|
||||
int listSize; // 有效空间大小
|
||||
HashCode hashCode; // 哈希函数
|
||||
Equal equal; // 判等函数
|
||||
Entry list; // 存储区域
|
||||
Put put; // 添加键的函数
|
||||
Get get; // 获取键对应值的函数
|
||||
Remove remove; // 删除键
|
||||
Clear clear; // 清空Map
|
||||
Exists exists; // 判断键是否存在
|
||||
Boolean autoAssign; // 设定是否根据当前数据量动态调整内存大小,默认开启
|
||||
}*HashMap;
|
||||
|
||||
// 迭代器结构
|
||||
typedef struct hashMapIterator {
|
||||
Entry entry; // 迭代器当前指向
|
||||
int count; // 迭代次数
|
||||
int hashCode; // 键值对的哈希值
|
||||
HashMap hashMap;
|
||||
}*HashMapIterator;
|
||||
|
||||
#define newHashMapIterator() NEW(struct hashMapIterator)
|
||||
|
||||
// 默认哈希函数
|
||||
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__
|
||||
/*
|
||||
* Copyright (c) 2020 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file: test_hash.h
|
||||
* @brief: declaration of hashtable
|
||||
* @version: 1.0
|
||||
* @author: Ambrumf
|
||||
* @date: 2023/9/12
|
||||
*/
|
||||
|
||||
#ifndef HASHTABLE_H
|
||||
#define HASHTABLE_H
|
||||
#include<stdbool.h>
|
||||
#include<stdlib.h>
|
||||
#include<stdio.h>
|
||||
#include<string.h>
|
||||
#include<transform.h>
|
||||
|
||||
typedef struct CharList{
|
||||
|
||||
struct CharList* next;
|
||||
char *data;
|
||||
|
||||
}CharList;
|
||||
|
||||
CharList* InitCharList();
|
||||
|
||||
void DeleteList(CharList *list);
|
||||
|
||||
typedef struct HashTable{
|
||||
struct CharList **list;
|
||||
int table_size;
|
||||
}HashTable;
|
||||
|
||||
int GetHashCode(char *str,int size);
|
||||
|
||||
HashTable* CreateHashTable(int size);
|
||||
|
||||
bool FindData(HashTable *table,char *str);
|
||||
|
||||
bool InsertData(HashTable *Table,char *str);
|
||||
|
||||
bool DeleteData(HashTable *Table,char *str);
|
||||
|
||||
void ClearTable(HashTable *Table);
|
||||
|
||||
#endif
|