firstCommit

This commit is contained in:
JhonLi 2023-09-25 00:28:13 -07:00
parent a1df906d16
commit ee6552bb8a
13 changed files with 134 additions and 239 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 102 KiB

34
APP_Framework/Applications/app_test/test_hash/README.md Normal file → Executable file
View File

@ -1,19 +1,14 @@
# 基于cortex-m3-emulator实现哈希表并测试验证##
# 基于cortex-m3-emulator实现哈希表并测试验证
## 1. 简介
利用c语言实现了哈希表HashMap包括添加键值对(Put),获取键对应的值(Get), 删除健Delete清空哈希表(Clear) 迭代遍历哈希表(hashMapIterator)等功能
操作。
利用c语言实现了哈希表HashMap包括添加键值对(Put),获取键对应的值(Get), 删除健Delete清空哈希表(Clear)等功能。参考了比赛提供的示例代码,通过使用与比赛截然不同的方法——线性探测法来解决哈希冲突。
利用数组Entry作为存储空间利用链表(*next)解决冲突。当哈希表的大小超过数组大小后,为避免发生冲突过多的情况,可以对哈希表扩容。
## 2. 数据结构设计说明
键值对结构
typedef struct entry {
void * key; // 键
void * value; // 值
struct entry * next; // 冲突链表
}*Entry;
哈希结构
typedef struct hashMap {
int size; // 当前大小
@ -28,7 +23,6 @@ typedef struct hashMap {
Exists exists; // 判断键是否存在
Boolean autoAssign; // 设定是否根据当前数据量动态调整内存大小,默认开启
}*HashMap;
包括以下函数功能,分别为:
`createHashMap`:创建一个哈希结构
`defaultPut`:添加键值对
@ -38,21 +32,19 @@ typedef struct hashMap {
`defaultClear`清空Map的函数类型
`resetHashMap`:重新构建哈希表
## 3. 测试程序说明
测试了哈希表的插入键值对(Put),判断键是否存在(Exist),获取键对应的值(Get) 删除健Delete,迭代遍历哈希表(hashMapIterator),清空哈希表(Clear)等操作。
并展示了利用链地址法解决哈希冲突的示例, 两个不同的人(Bob和Li Ming)的hashcode相同。
测试了哈希表的插入键值对(Put),判断键是否存在(Exist),获取键对应的值(Get) 删除健Delete等操作。
## 4. 运行结果(##需结合运行测试截图按步骤说明##
![image](ConfigOpen.png)
打开menuconfig之后将test_hash_map开启(y),保存后退出
4.1打开menuconfig之后将test_hash_map开启(y),保存后退出。
![image](01.png)
![image](02.png)
![image](03.png)
![image](04.png)
![image](CompileSuccess.png)
编译XiZi-cortex-m3-emulator.elf成功
![image](ShellCommand.png)
启动qemu模拟Xiuos操作系统验证TestHash注册Shell命令
![image](TestHash.png)
执行TestHash命令打印测试结果。
4.2编译XiZi-cortex-m3-emulator.elf成功。
![image](05.png)
4.3启动qemu模拟Xiuos操作系统验证TestHash注册Shell命令。执行TestHash命令打印测试结果。
![image](06.png)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 KiB

152
APP_Framework/Applications/app_test/test_hash/test_hash.c Normal file → Executable file
View File

@ -2,12 +2,11 @@
/**
* @file: test_hash.c
* @brief: a application of test hash function
* @version: 3.0
* @author: Yao wenying
* @date: 2023/05/26
* @version: 1.0
* @author: Li chunji And Li zihao
* @date: 2023/09/15
*/
#include <transform.h>
#include"test_hash.h"
int defaultHashCode(HashMap hashMap, let key) {
@ -35,16 +34,12 @@ void resetHashMap(HashMap hashMap, int listSize) {
// 键值对临时存储空间
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;
for(int index=0;index<hashMap->listSize;index++)
{
tempList[index].key = hashMap->list[index].key;
tempList[index].value = hashMap->list[index].value;
}
freeHashMapIterator(&iterator);
// 清除原有键值对数据
hashMap->size = 0;
@ -52,13 +47,6 @@ void resetHashMap(HashMap hashMap, int listSize) {
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;
}
}
}
// 更改内存大小
@ -73,7 +61,6 @@ void resetHashMap(HashMap hashMap, int listSize) {
for (int i = 0; i < hashMap->listSize; i++) {
hashMap->list[i].key = NULL;
hashMap->list[i].value = NULL;
hashMap->list[i].next = NULL;
}
// 将所有键值对重新写入内存
@ -95,33 +82,18 @@ void defaultPut(HashMap hashMap, let key, let value) {
}
else {
Entry current = &hashMap->list[index];
while (current != NULL) {
if (hashMap->equal(key, current->key)) {
// 对于键值已经存在的直接覆盖
current->value = value;
return;
int cur = (index+1) % hashMap->listSize;
while(hashMap->list[cur].key != NULL)
{
cur = (cur + 1) % hashMap->listSize;
}
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++;
hashMap->list[index].key = key;
hashMap->list[index].value = value;
}
if (hashMap->autoAssign && hashMap->size >= hashMap->listSize) {
// 内存扩充至原来的两倍
// *注: 扩充时考虑的是当前存储元素数量与存储空间的大小关系,而不是存储空间是否已经存满,
// 例如: 存储空间为10存入了10个键值对但是全部冲突了所以存储空间空着9个其余的全部挂在一个上面
// 这样检索的时候和遍历查询没有什么区别了可以简单这样理解当我存入第11个键值对的时候一定会发生冲突
// 这是由哈希函数本身的特性(取模)决定的,冲突就会导致检索变慢,所以这时候扩充存储空间,对原有键值对进行
// 再次散列,会把冲突的数据再次分散开,加快索引定位速度。
resetHashMap(hashMap, hashMap->listSize * 2);
}
}
@ -134,7 +106,8 @@ let defaultGet(HashMap hashMap, let key) {
if (hashMap->equal(entry->key, key)) {
return entry->value;
}
entry = entry->next;
index++;
entry = &hashMap->list[index % hashMap->listSize];
}
}
return NULL;
@ -146,37 +119,29 @@ let defaultRemove(HashMap hashMap, let key) {
if (entry->key == NULL) {
return NULL;
}
let entryKey = entry->key;
let entryKey = 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;
Entry entry = &hashMap->list[(index+1)%hashMap->listSize];
while (entry != NULL) {
if (hashMap->equal(entry->key, key)) {
hashMap->size--;
p->next = entry->next;
free(entry);
entry->key = NULL;
entry->value = NULL;
result = True;
break;
}
p = entry;
entry = entry->next;
};
index++;
entry = &hashMap->list[index % hashMap->listSize];
}
}
// 如果空间占用不足一半,则释放多余内存
@ -193,27 +158,20 @@ Boolean defaultExists(HashMap hashMap, let key) {
return False;
}
else {
while (entry != NULL) {
if (hashMap->equal(entry->key, key)) {
return True;
}
entry = entry->next;
index++;
entry = &hashMap->list[index % hashMap->listSize];
}
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;
@ -244,50 +202,11 @@ HashMap createHashMap(HashCode hashCode, Equal equal) {
}
Entry p = hashMap->list;
for (int i = 0; i < hashMap->listSize; i++) {
p[i].key = p[i].value = p[i].next = NULL;
p[i].key = p[i].value = 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)
@ -305,19 +224,20 @@ void TestHash() {
Put(map, "000852", "Janne");
printf("print the key-values in hashmap:\n");
HashMapIterator iterator = createHashMapIterator(map);
while (hasNextHashMapIterator(iterator)) {
iterator = nextHashMapIterator(iterator);
for(int index=0;index<map->listSize;index++)
{
if(defaultExists(map, map->list[index].key))
{
printf("{ key: %s, key: %s, hashcode: %d }\n",
(char *)iterator->entry->key, (char *)iterator->entry->value, iterator->hashCode);
(char *)map->list[index].key, (char *)map->list[index].value, map->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);

View File

@ -1,13 +1,14 @@
/**
* @file: test_hash.h
* @brief: a application of test hash function
* @version: 3.0
* @author: Yao wenying
* @date: 2023/05/26
* @file: test_hash.c
* @brief: an application of test hash function
* @version: 1.0
* @author: Li chunji And Li zihao
* @date: 2023/9/15
*/
#ifndef __HASHMAP_H__
#define __HASHMAP_H__
@ -31,7 +32,6 @@ typedef enum _Boolean Boolean;
typedef struct entry {
let key; // 键
let value; // 值
struct entry * next; // 冲突链表
}*Entry;
#define newEntry() NEW(struct entry)
@ -77,15 +77,9 @@ typedef struct hashMap {
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);
@ -114,16 +108,5 @@ 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__