热身赛一级赛题3

This commit is contained in:
zhong 2023-07-08 15:06:16 +08:00
parent 7754a149a9
commit 8e06261da6
11 changed files with 405 additions and 0 deletions

View File

@ -240,5 +240,8 @@ menu "test app"
bool "Config test soft timer"
default n
menuconfig USER_TEST_HASH
bool "Config test hash table"
default n
endif
endmenu

View File

@ -99,6 +99,10 @@ ifeq ($(CONFIG_ADD_XIZI_FETURES),y)
ifeq ($(CONFIG_USER_TEST_TIMER),y)
SRC_FILES += test_timer.c
endif
ifeq ($(CONFIG_USER_TEST_HASH),y)
SRC_FILES += test_hash/test_hash.c
endif
include $(KERNEL_ROOT)/compiler.mk

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 309 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 346 KiB

View File

@ -0,0 +1,74 @@
# 哈希表
## 1. 简介
散列表Hash table也叫哈希表是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。
## 2. 数据结构设计说明
哈希表节点元素及哈希表设计如下:
```
typedef struct kv
{
struct kv* next;
char* key;
void* value;
}kv;
/* HashTable */
typedef struct HashTable
{
struct kv ** table;
}HashTable;
```
其中一共实现了8个函数分别为
- `init_kv`:构造一个哈希表节点并初始化
- `free_kv`:删除一个哈希表节点
- `hash_33`经典Times33哈希函数
- `hash_table_delete`:销毁一个哈希表
- `hash_table_new`:构造一个哈希表并初始化
- `hash_table_put2`根据key插入或更新value
- `hash_table_get`根据key获取value
- `hash_table_rm`根据key移除一个键值对
## 3. 测试程序说明
测试程序 `TestHash` 已经注册为 shell 命令,可以调用执行。
测试程序定义了以下键值对:
```
char keys[][MAX_WORD_LEN] = {
"what",
"where",
"why",
"how",
"hello!",
"apple",
"12345"
};
int values[] = {1, 2, 3, 4, 5, 6, 7};
```
1.程序的第一部分创建了哈希表,并且将定义的 7 个键值对的前 6 个插入了基数树,然后分别查找 7 个键,前 6 个均可以找到对应的值,最后一个未插入,因此无法找到
2.程序的第二部分从哈希表中删除了 where 和 how 两个键,再次分别查找 7 个键,删除的键值对和未插入的键值对均无法找到
3.程序的第三部分重新插入了已删除的 where 和未插入过的 12345 ,再次分别查找 7 个键,新插入的值可以检索到
4.程序的第四部分将哈希表销毁,再次分别查找 7 个键,所有的键值对均无法找到
## 4. 运行结果(需结合运行测试截图按步骤说明)
1.在工作区终端中输入命令,进入配置页面
```
cd /xiuos/Ubiquitous/XiZi_IIoT
make BOARD=cortex-m3-emulator menuconfig
```
![fig1](1.png)
2.依次进入 `APP_Framework` -> `Applications` -> `test app` 目录,将 `Enable application test function` 选项置为 `Y`
![fig2](2.png)
3.进入 `Enable application test function``Config test hash table` 选项置为 `Y`
![fig3](3.png)
4.一直选择 `Exit` 退出配置,在最后需要确认的页面选择 `Yes` 保存配置
5.执行编译命令:`make BOARD=cortex-m3-emulator`,正常情况下应当编译无误
![fig4](4.png)
6.在 `qemu` 中运行:`qemu-system-arm -machine lm3s6965evb -nographic -kernel build/XiZi-cortex-m3-emulator.elf`
![fig5](5.png)
7.在 shell 中运行命令 `TestHash`,执行结果与预期一致,验证完成。
![fig6](6.png)

View File

@ -0,0 +1,292 @@
/**
* @file: test_hash.c
* @brief: Implement a simple hash
* @version: 1.0
* @date: 2023/5/29
*/
#include <transform.h>
#include "test_hash.h"
#define TABLE_SIZE 1024
#define MAX_WORD_LEN 128
/**
* @description: element of the hash table's chain list
* free_value is the destructor of value
*/
typedef struct kv
{
struct kv* next;
char* key;
void* value;
// void(*free_value)(void*);
}kv;
/* HashTable */
typedef struct HashTable
{
struct kv ** table;
}HashTable;
/**
* @description: constructor of struct kv
* @param kv - element of the hash table's chain list
* @return void
*/
void init_kv(struct kv* kv)
{
kv->next = NULL;
kv->key = NULL;
kv->value = NULL;
// kv->free_value = NULL;
}
/**
* @description: destructor of struct kv
* @param kv - element of the hash table's chain list
* @return void
*/
static void free_kv(struct kv* kv)
{
if (kv) {
// if (kv->free_value) {
// kv->free_value(kv->value);
// }
free(kv->key);
// free(kv->value);
kv->key = NULL;
free(kv);
}
}
/**
* @description: the classic Times33 hash function
* @param key - hash key
* @return unsigned int
*/
static unsigned int hash_33(char* key)
{
unsigned int hash = 0;
while (*key) {
hash = (hash << 5) + hash + *key++;
}
return hash;
}
/**
* @description: delete a HashTable instance
* @param ht - HashTable*
* @return void
*/
void hash_table_delete(HashTable* ht)
{
if (ht) {
if (ht->table) {
int i = 0;
for (i = 0; i<TABLE_SIZE&&ht->table[i]!=NULL; i++) {
struct kv* p = ht->table[i];
struct kv* q = NULL;
while (p) {
q = p->next;
free_kv(p);
p = q;
}
}
free(ht->table);
ht->table = NULL;
}
free(ht);
}
}
/**
* @description: new a HashTable instance
* @return HashTable*
*/
HashTable* hash_table_new()
{
HashTable* ht = malloc(sizeof(HashTable));
if (NULL == ht) {
hash_table_delete(ht);
return NULL;
}
ht->table = malloc(sizeof(struct kv*) * TABLE_SIZE);
if (NULL == ht->table) {
hash_table_delete(ht);
return NULL;
}
memset(ht->table, 0, sizeof(struct kv*) * TABLE_SIZE);
return ht;
}
/**
* @description: insert or update a value indexed by key
* @param ht - radix tree root
* @param key - new key
* @param value - new value
* @return int
*/
int hash_table_put2(HashTable* ht, char* key, void* value)
{
int i = hash_33(key) % TABLE_SIZE;
struct kv* p = ht->table[i];
struct kv* prep = p;
while (p) { /* if key is already stroed, update its value */
if (strcmp(p->key, key) == 0) {
// free(p->value);
p->value = value;
break;
}
prep = p;
p = p->next;
}
if (p == NULL) {/* if key has not been stored, then add it */
char* kstr = malloc(strlen(key) + 1);
if (kstr == NULL) {
return -1;
}
struct kv * kv = malloc(sizeof(struct kv));
if (NULL == kv) {
free(kstr);
kstr = NULL;
return -1;
}
init_kv(kv);
kv->next = NULL;
strcpy(kstr, key);
kv->key = kstr;
kv->value = value;
if (prep == NULL) {
ht->table[i] = kv;
}
else {
prep->next = kv;
}
}
return 0;
}
/**
* @description: get a value indexed by key
* @param ht - radix tree root
* @param key - new key
* @return void* value
*/
void* hash_table_get(HashTable* ht, char* key)
{
if(ht == NULL)return NULL;
int i = hash_33(key) % TABLE_SIZE;
struct kv* p = ht->table[i];
while (p) {
if (strcmp(key, p->key) == 0) {
return p->value;
}
p = p->next;
}
return NULL;
}
/**
* @description: remove a value indexed by key
* @param ht - radix tree root
* @param key - new key
* @return void
*/
void hash_table_rm(HashTable* ht, char* key)
{
int i = hash_33(key) % TABLE_SIZE;
struct kv* p = ht->table[i];
struct kv* prep = p;
while (p) {
if (strcmp(key, p->key) == 0) {
free_kv(p);
if (p == prep) {
if(NULL==p->next)
ht->table[i] = NULL;
else
ht->table[i]=p->next;
}
else {
prep->next = p->next;
}
break;
}
prep = p;
p = p->next;
}
}
void TestHash()
{
char keys[][MAX_WORD_LEN] = {
"what",
"where",
"why",
"how",
"hello!",
"apple",
"12345"
};
int values[] = {1, 2, 3, 4, 5, 6, 7};
printf("\nCreate hash table and add key & value:\n");
HashTable* ht = hash_table_new();
if (NULL == ht) {
printf("Create hash table failed.\n");
return;
}
// insert key&value into hash table
int num = sizeof(keys) / sizeof(keys[0]);
for (int i = 0; i < num - 1; ++i) {
hash_table_put2(ht, keys[i], &values[i]);
}
//find value by key
for (int i = 0; i < num; ++i) {
int* v = (int*)hash_table_get(ht, keys[i]);
if (v) printf("keys[%d] \"%s\"'v = %d, values[%d] = %d\n", i, keys[i], *v, i, values[i]);
else printf("keys[%d] \"%s\" not found\n", i, keys[i]);
}
printf("\nDelete \"where\" and \"how\":\n");
hash_table_rm(ht, keys[1]);
hash_table_rm(ht, keys[3]);
for (int i = 0; i < num; ++i) {
int* v = (int*)hash_table_get(ht, keys[i]);
if (v) printf("keys[%d] \"%s\"'v = %d, values[%d] = %d\n", i, keys[i], *v, i, values[i]);
else printf("keys[%d] \"%s\" not found\n", i, keys[i]);
}
printf("\nInsert \"where\" and \"12345\":\n");
hash_table_put2(ht, keys[1], &values[1]);
hash_table_put2(ht, keys[6], &values[6]);
for (int i = 0; i < num; ++i) {
int* v = (int*)hash_table_get(ht, keys[i]);
if (v) printf("keys[%d] \"%s\"'v = %d, values[%d] = %d\n", i, keys[i], *v, i, values[i]);
else printf("keys[%d] \"%s\" not found\n", i, keys[i]);
}
printf("\nDestroy hash table:\n");
hash_table_delete(ht);
ht = NULL;
for (int i = 0; i < num; ++i) {
int* v = (int*)hash_table_get(ht, keys[i]);
if (v) printf("keys[%d] \"%s\"'v = %d, values[%d] = %d\n", i, keys[i], *v, i, values[i]);
else printf("keys[%d] \"%s\" not found\n", i, keys[i]);
}
return;
}
PRIV_SHELL_CMD_FUNCTION(TestHash, Implement a simple hash, PRIV_SHELL_CMD_MAIN_ATTR);

View File

@ -0,0 +1,32 @@
#pragma once
typedef struct HashTable HashTable;
#ifdef __cplusplus
extern "C" {
#endif
/* new an instance of HashTable */
HashTable* hash_table_new();
/*
delete an instance of HashTable,
all values are removed auotmatically.
*/
void hash_table_delete(HashTable* ht);
/*
add or update a value to ht,
free_value(if not NULL) is called automatically when the value is removed.
return 0 if success, -1 if error occurred.
*/
int hash_table_put2(HashTable* ht, char* key, void* value);
/* get a value indexed by key, return NULL if not found. */
void* hash_table_get(HashTable* ht, char* key);
/* remove a value indexed by key */
void hash_table_rm(HashTable* ht, char* key);
#ifdef __cplusplus
}
#endif