当前位置:   article > 正文

哈希表的原理及其算法实现(C/C++描述)_c++哈希表的内部实现原理

c++哈希表的内部实现原理

目录

定义

相关属性

算法实现

1)数据结构

2)哈希函数

3)哈希链表初始化

4)哈希链表查找元素

5)哈希链表插入元素

6)哈希表删除元素

程序清单


定义

哈希表 - 散列表,它是基于快速存取的角度设计的,也是一种典型的“空间换时间”的做法。

相关属性

键(key): 组员的编号 如, 1 、 5 、 19 
值(value): 组员的其它信息(包含 性别、年龄和战斗力等)
索引: 数组的下标(0,1,2,3,4) ,用以快速定位和检索数据
哈希桶: 保存索引的数组(链表或数组),数组成员为每一个索引值相同的多个元素
哈希函数: 将组员编号映射到索引上 ,采用求余法 ,如: 组员编号 19

算法实现

1)数据结构

  1. #define DEFAULT_SIZE 3 //默认哈希表大小是3
  2. typedef struct _ListNode
  3. {
  4. int key;
  5. int data;
  6. struct _ListNode *next;
  7. }ListNode,*List,*Element;//List作为每个哈希桶的头结点,不保存元素
  8. typedef struct _HashTable
  9. {
  10. List *Lists;//保存所有哈希桶头结点的数组
  11. int tableSize;//数组大小 也即哈希桶的个数
  12. }HashTable;

2哈希函数

  1. //求余数法 根据key 定为桶的位置
  2. int Hash(int key, int tableSize)
  3. {
  4. return (key%tableSize);
  5. }

 3)哈希链表初始化

  1. //初始化哈希表
  2. HashTable * InitHashTable(int tableSize)
  3. {
  4. HashTable *ht=new HashTable;
  5. if (!ht) return NULL;
  6. tableSize <= 0 ? DEFAULT_SIZE : tableSize;//如果哈希表数组大小小于等于0 则取默认大小
  7. ht->tableSize = tableSize;
  8. ht->Lists = new List[tableSize];
  9. if (!ht->Lists)
  10. {
  11. delete ht;
  12. return NULL;
  13. }
  14. //为数组中每一个哈希桶的头结点初始化
  15. for (int i=0;i<tableSize;i++)
  16. {
  17. ht->Lists[i] = new ListNode;
  18. if (!ht->Lists[i])
  19. {
  20. delete ht->Lists;
  21. delete ht;
  22. return NULL;
  23. }
  24. //并将头结点置空
  25. memset(ht->Lists[i], 0, sizeof(ListNode));
  26. }
  27. return ht;
  28. }

4)哈希链表查找元素

  1. //根据key值查找哈希表中元素
  2. Element Find(HashTable *ht,int key)
  3. {
  4. int i = Hash(key, ht->tableSize);
  5. Element tmp = NULL;
  6. tmp = ht->Lists[i]->next; //取出key所在数据桶的第一个元素
  7. while (tmp!=NULL)
  8. {
  9. if (tmp->key == key) return tmp;//找到相同元素则将元素返回
  10. else tmp = tmp->next;//没有找到则继续找下一个
  11. }
  12. return tmp;
  13. }

5)哈希链表插入元素

  1. //插入元素
  2. bool InsertHashTable(HashTable* &ht, int key, int value)
  3. {
  4. if (Find(ht, key) != NULL)//如果找到了相对应的key的元素 则证明插入元素已经因为存在 因为键值key是惟一的
  5. {
  6. printf("Element has existed !");
  7. return false;
  8. }
  9. Element L = ht->Lists[Hash(key,ht->tableSize)];//找出 key所对应哈希桶的头结点
  10. //采用头插法插入元素
  11. Element q = new ListNode;
  12. if (!q) return false;
  13. q->data = value;
  14. q->key = key;
  15. q->next = L->next;
  16. L->next = q;
  17. return true;
  18. }

6哈希表删除元素

  1. bool DeleteHashNode(HashTable* &ht, int key)
  2. {
  3. int i = Hash(key, ht->tableSize);
  4. List L = ht->Lists[i];//找到key所在哈希桶的头结点
  5. Element e = L->next;//找到第一个元素
  6. while (e != NULL && e->key!=key)
  7. {
  8. L = e;
  9. e = e->next;
  10. }
  11. if (e == NULL)
  12. return false; //如果没有找到key所对应的元素 返回false
  13. //从桶链表中删除元素e
  14. L->next = e->next;
  15. delete e;
  16. return true;
  17. }

程序清单

  1. // 哈希表Hash.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
  2. //Author:See QQ3492625357
  3. //代码为手写,程序通过简单测试,其中可能有误或不当之处欢迎指正
  4. #include <iostream>
  5. #define DEFAULT_SIZE 3 //默认哈希表大小是3
  6. typedef struct _ListNode
  7. {
  8. int key;
  9. int data;
  10. struct _ListNode *next;
  11. }ListNode,*List,*Element;//List作为每个哈希桶的头结点,不保存元素
  12. typedef struct _HashTable
  13. {
  14. List *Lists;//保存所有哈希桶头结点的数组
  15. int tableSize;//数组大小 也即哈希桶的个数
  16. }HashTable;
  17. //求余数法 根据key 定为桶的位置
  18. int Hash(int key, int tableSize)
  19. {
  20. return (key%tableSize);
  21. }
  22. //初始化哈希表
  23. HashTable * InitHashTable(int tableSize)
  24. {
  25. HashTable *ht=new HashTable;
  26. if (!ht) return NULL;
  27. tableSize <= 0 ? DEFAULT_SIZE : tableSize;//如果哈希表数组大小小于等于0 则取默认大小
  28. ht->tableSize = tableSize;
  29. ht->Lists = new List[tableSize];
  30. if (!ht->Lists)
  31. {
  32. delete ht;
  33. return NULL;
  34. }
  35. //为数组中每一个哈希桶的头结点初始化
  36. for (int i=0;i<tableSize;i++)
  37. {
  38. ht->Lists[i] = new ListNode;
  39. if (!ht->Lists[i])
  40. {
  41. delete ht->Lists;
  42. delete ht;
  43. return NULL;
  44. }
  45. //并将头结点置空
  46. memset(ht->Lists[i], 0, sizeof(ListNode));
  47. }
  48. return ht;
  49. }
  50. //根据key值查找哈希表中元素
  51. Element Find(HashTable *ht,int key)
  52. {
  53. int i = Hash(key, ht->tableSize);
  54. Element tmp = NULL;
  55. tmp = ht->Lists[i]->next; //取出key所在数据桶的第一个元素
  56. while (tmp!=NULL)
  57. {
  58. if (tmp->key == key) return tmp;//找到相同元素则将元素返回
  59. else tmp = tmp->next;//没有找到则继续找下一个
  60. }
  61. return tmp;
  62. }
  63. //插入元素
  64. bool InsertHashTable(HashTable* &ht, int key, int value)
  65. {
  66. if (Find(ht, key) != NULL)//如果找到了相对应的key的元素 则证明插入元素已经因为存在 因为键值key是惟一的
  67. {
  68. printf("Element has existed !");
  69. return false;
  70. }
  71. Element L = ht->Lists[Hash(key,ht->tableSize)];//找出 key所对应哈希桶的头结点
  72. //采用头插法插入元素
  73. Element q = new ListNode;
  74. if (!q) return false;
  75. q->data = value;
  76. q->key = key;
  77. q->next = L->next;
  78. L->next = q;
  79. return true;
  80. }
  81. //删除元素
  82. bool DeleteHashNode(HashTable* &ht, int key)
  83. {
  84. int i = Hash(key, ht->tableSize);
  85. List L = ht->Lists[i];//找到key所在哈希桶的头结点
  86. Element e = L->next;//找到第一个元素
  87. while (e != NULL && e->key!=key)
  88. {
  89. L = e;
  90. e = e->next;
  91. }
  92. if (e == NULL)
  93. return false; //如果没有找到key所对应的元素 返回false
  94. //从桶链表中删除元素e
  95. L->next = e->next;
  96. delete e;
  97. return true;
  98. }
  99. int main()
  100. {
  101. int elem[] = { 100,200,300,400,500,600,700,800,900 };
  102. HashTable *HT = NULL;
  103. HT = InitHashTable(DEFAULT_SIZE);
  104. if (!HT) return -1;
  105. for (int i=0;i< sizeof(elem) / sizeof(elem[0]);i++)
  106. {
  107. InsertHashTable(HT, i, elem[i]);
  108. }
  109. //输出测试
  110. for (int i = 0; i < sizeof(elem) / sizeof(elem[0]); i++)
  111. {
  112. Element tmp = Find(HT, i);
  113. if (tmp!=NULL)
  114. {
  115. std::cout << tmp->data << " ";
  116. }
  117. }
  118. std::cout << std::endl;
  119. //把key=3删除 测试输出结果
  120. DeleteHashNode(HT, 3);
  121. std::cout << "删除key=3 value=400 后 输出哈希表" << std::endl;
  122. for (int i = 0; i < sizeof(elem) / sizeof(elem[0]); i++)
  123. {
  124. Element tmp = Find(HT, i);
  125. if (tmp != NULL)
  126. {
  127. std::cout << tmp->data << " ";
  128. }
  129. }
  130. std::cout << std::endl;
  131. system("pause");
  132. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/喵喵爱编程/article/detail/748135
推荐阅读
相关标签
  

闽ICP备14008679号