[应用相关] 哈希表实现菜单方法

[复制链接]
556|12
 楼主| 小明的同学 发表于 2023-4-26 20:40 | 显示全部楼层 |阅读模式
哈希表是一种常用的数据结构,可以用于实现菜单功能。哈希表的基本思想是将菜单项名称映射为一个哈希值,然后将哈希值作为下标,将菜单项存储在数组中。哈希表的优点是能够快速定位菜单项,查找的时间复杂度为常数级别,而且具有较好的空间利用率。

哈希表实现菜单的步骤如下:

创建哈希表:创建一个哈希表,用于存储菜单项。哈希表通常是一个固定大小的数组,数组中的每个元素都是一个链表,用于存储哈希值相同的菜单项。

计算哈希值:将菜单项名称转化为哈希值,可以使用一些常用的哈希算法,例如MD5、SHA1等。

存储菜单项:将计算得到的哈希值作为下标,在哈希表中查找对应的链表。如果链表为空,则创建一个节点,并将菜单项存储在节点中;否则,在链表的末尾添加一个节点,存储菜单项。

查找菜单项:将菜单项名称转化为哈希值,使用哈希值在哈希表中查找对应的链表,然后遍历链表,查找菜单项。如果找到菜单项,则返回对应的菜单项;否则,返回菜单不存在的提示信息。

删除菜单项:将菜单项名称转化为哈希值,使用哈希值在哈希表中查找对应的链表,然后遍历链表,查找要删除的菜单项。如果找到菜单项,则删除对应的节点;否则,返回菜单不存在的提示信息。

哈希表实现菜单的优点是能够快速定位菜单项,具有较好的空间利用率,适用于需要快速查找菜单项的场景。缺点是实现较为复杂,需要考虑哈希冲突等问题。此外,哈希表的实现需要一些较为复杂的算法,不适用于初学者。

 楼主| 小明的同学 发表于 2023-4-26 20:41 | 显示全部楼层
  1. #include <stdio.h>
  2. #include <string.h>

  3. #define HASH_TABLE_SIZE 16

  4. typedef struct menu_node {
  5.     char name[32];
  6.     void (*func)(void);
  7.     struct menu_node *next;
  8. } MenuNode;

  9. MenuNode *hash_table[HASH_TABLE_SIZE];

  10. unsigned int hash_func(const char *str) {
  11.     unsigned int hash = 5381;
  12.     while (*str) {
  13.         hash = ((hash << 5) + hash) + (*str++);
  14.     }
  15.     return hash;
  16. }

  17. void menu_add(const char *name, void (*func)(void)) {
  18.     unsigned int hash = hash_func(name) % HASH_TABLE_SIZE;
  19.     MenuNode *node = hash_table[hash];
  20.     while (node != NULL) {
  21.         if (strcmp(node->name, name) == 0) {
  22.             // 菜单项已存在,更新函数指针
  23.             node->func = func;
  24.             return;
  25.         }
  26.         node = node->next;
  27.     }
  28.     // 创建新节点
  29.     node = (MenuNode *)malloc(sizeof(MenuNode));
  30.     strcpy(node->name, name);
  31.     node->func = func;
  32.     node->next = hash_table[hash];
  33.     hash_table[hash] = node;
  34. }

  35. void menu_remove(const char *name) {
  36.     unsigned int hash = hash_func(name) % HASH_TABLE_SIZE;
  37.     MenuNode *node = hash_table[hash];
  38.     MenuNode *prev = NULL;
  39.     while (node != NULL) {
  40.         if (strcmp(node->name, name) == 0) {
  41.             // 找到要删除的节点
  42.             if (prev != NULL) {
  43.                 prev->next = node->next;
  44.             } else {
  45.                 hash_table[hash] = node->next;
  46.             }
  47.             free(node);
  48.             return;
  49.         }
  50.         prev = node;
  51.         node = node->next;
  52.     }
  53. }

  54. void menu_run(const char *name) {
  55.     unsigned int hash = hash_func(name) % HASH_TABLE_SIZE;
  56.     MenuNode *node = hash_table[hash];
  57.     while (node != NULL) {
  58.         if (strcmp(node->name, name) == 0) {
  59.             // 执行对应的菜单项函数
  60.             node->func();
  61.             return;
  62.         }
  63.         node = node->next;
  64.     }
  65.     printf("菜单项不存在!\n");
  66. }

  67. void menu_func1(void) {
  68.     printf("执行菜单项1\n");
  69. }

  70. void menu_func2(void) {
  71.     printf("执行菜单项2\n");
  72. }

  73. int main() {
  74.     // 添加菜单项
  75.     menu_add("item1", menu_func1);
  76.     menu_add("item2", menu_func2);

  77.     // 运行菜单项
  78.     menu_run("item1");
  79.     menu_run("item2");

  80.     // 删除菜单项
  81.     menu_remove("item2");

  82.     return 0;
  83. }
 楼主| 小明的同学 发表于 2023-4-26 20:41 | 显示全部楼层
在上面的代码中,哈希表的大小为16,使用了简单的哈希算法(djb2)计算哈希值。menu_add函数用于添加菜单项,如果菜单项已存在,则更新函数指针;menu_remove函数用于删除菜单项;menu_run函数用于运行菜单项对应的函数。在示例代码中,添加了两个菜单项并运行了它们,然后删除了
公羊子丹 发表于 2024-6-11 07:01 | 显示全部楼层

主电路那些环路产生的噪声会加到控制信号上
万图 发表于 2024-6-11 08:04 | 显示全部楼层

多次检查也会给单片机带来负荷,对功耗不利
Uriah 发表于 2024-6-11 09:07 | 显示全部楼层

在GR-SAKURA中,从IO30引脚到IO35引脚接收来自外部的中断信号
帛灿灿 发表于 2024-6-11 11:03 | 显示全部楼层

在掌握对象的变化频度时是有效的
Bblythe 发表于 2024-6-11 12:06 | 显示全部楼层

中断信号直接从各外部设备通知中断控制器
周半梅 发表于 2024-6-11 14:02 | 显示全部楼层

通过交流电源插头从产品中流走
Pulitzer 发表于 2024-6-11 15:05 | 显示全部楼层

来自单 片机内部的定时器和GPIO、串行通信设备UART等外设机器的中断被称为外部设备中断
童雨竹 发表于 2024-6-11 17:01 | 显示全部楼层

交流电压在发射EMI
Wordsworth 发表于 2024-6-11 18:04 | 显示全部楼层

中断产生于单片机内部和外部的各种设备
Clyde011 发表于 2024-6-11 19:07 | 显示全部楼层

这样的设定只需在setup()中定义一次便能在整个程序中有效
您需要登录后才可以回帖 登录 | 注册

本版积分规则

159

主题

1640

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部