哈希表查找代码实现

缺乏、安全感 2022-06-18 04:18 283阅读 0赞

前言

  1. 博客编写人:Willam
  2. 博客编写时间:2017/3/29
  3. 博主邮箱:2930526477@qq.com(有志同道合之人,可以加qq交流交流编程心得)

1、代码实现的介绍

下面我将会实现哈希表的查找代码:
其中我会采取的散列构造函数为最常用的构造函数:除留取余数法
而解决冲突的方法采用以下三种,分别实现:

  1. 线性探测
  2. 二次探测
  3. 链地址法

如果需要了解哈希表的详细介绍,可参考博客:哈希表的详解

2、线性探测的实现

  • linear.h文件的代码

    /**/
    / 程序作者:Willam /
    / 程序完成时间:2017/3/29 /
    / 有任何问题请联系:2930526477@qq.com /
    /**/
    //@尽量写出完美的程序

  1. //#pragma once是一个比较常用的C/C++杂注,
  2. //只要在头文件的最开始加入这条杂注,
  3. //就能够保证头文件只被编译一次。
  4. #ifndef MY_H_FILE //如果没有定义这个宏
  5. #define MY_H_FILE //定义这个宏
  6. #include<iostream>
  7. using namespace std;
  8. typedef int Keytype;
  9. //每次都是取质数最接近的质数
  10. struct Hash {
  11. Keytype * elem; //记录哈希表中的元素
  12. bool * isfull; //记录哈希表是否有元素了
  13. int count; //哈希表中元素的个数
  14. int sizeindex;
  15. };
  16. bool searchHash(Hash t, Keytype k, int & p, int &c,int * hashsize);
  17. bool insertHash(Hash & t, Keytype k, int * hashsize);
  18. bool DeleteHash(Hash & t, Keytype k, int * hashsize);
  19. void print(Hash t, int * hashsize);
  20. #endif
  • linear.cpp文件的代码

    include”linear.h”

  1. //查找对应的关键字
  2. bool searchHash(Hash t, Keytype k, int & p,int &c,int * hashsize) {
  3. p = k%hashsize[t.sizeindex];
  4. while (t.isfull[p] && t.elem[p] != k && c < hashsize[t.sizeindex]-1) {
  5. ++c;
  6. //继续往下寻找下一个散列结点
  7. p=(k+c) % hashsize[t.sizeindex];
  8. }
  9. if (t.elem[p] == k) {
  10. return true;
  11. }
  12. return false;
  13. }
  14. bool insertHash(Hash & t, Keytype k, int * hashsize) {
  15. int p;
  16. int c = 0;
  17. if (searchHash(t, k, p,c,hashsize)) {
  18. return false;
  19. }
  20. else if (c==hashsize[t.sizeindex]-1) {
  21. //此时哈希表已经满,得重新分配了
  22. //首先是把之前的内容保存起来
  23. int temp;
  24. temp=hashsize[t.sizeindex];
  25. Keytype * elem = new Keytype[hashsize[t.sizeindex]];
  26. bool * isfull=new bool[hashsize[t.sizeindex]];
  27. for (int i = 0; i < hashsize[t.sizeindex]; ++i) {
  28. elem[i] = t.elem[i];
  29. isfull[i] = t.isfull[i];
  30. }
  31. delete t.elem;
  32. delete t.isfull;
  33. ++t.sizeindex;
  34. //重新分配空间
  35. t.elem= new Keytype[hashsize[t.sizeindex]];
  36. t.isfull=new bool[hashsize[t.sizeindex]];
  37. int i;
  38. for (i = 0; i < temp; ++i) {
  39. t.elem[i]=elem[i];
  40. t.isfull[i] = isfull[i];
  41. }
  42. for (; i < hashsize[t.sizeindex]; ++i) {
  43. t.isfull[i] = false;
  44. }
  45. }
  46. else {
  47. //cout << p << endl;
  48. //直接插入对应的位置
  49. t.elem[p] = k;
  50. ++t.count;
  51. t.isfull[p] = true;
  52. }
  53. }
  54. bool DeleteHash(Hash & t, Keytype k, int * hashsize) {
  55. int p;
  56. int c = 0;
  57. if (!searchHash(t, k, p, c,hashsize)) {
  58. //没找到要删除的元素
  59. return false;
  60. }
  61. else {
  62. t.isfull[p] = false;
  63. --t.count;
  64. }
  65. }
  66. void print(Hash t, int * hashsize) {
  67. cout << "当前的表的长度:" << hashsize[t.sizeindex] << endl;
  68. cout << "Hash表的元素个数为:" << t.count << endl;
  69. cout << "打印整个表:" << endl;
  70. for (int i = 0; i < hashsize[t.sizeindex]; ++i) {
  71. if(t.isfull[i])
  72. cout << t.elem[i] << " ";
  73. else {
  74. cout << "^" << " ";
  75. }
  76. }
  77. cout << endl;
  78. }
  • main.cpp文件的代码

    include”linear.h”

    int hashsize[]={ 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107,
    109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223,
    227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337,
    347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457,
    461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593,
    599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719,
    727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857,
    859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997 };
    int main() {

    1. Hash t;
    2. t.count = 0;
    3. t.sizeindex = 0;
    4. t.elem = new Keytype[hashsize[t.sizeindex]];
    5. t.isfull = new bool[hashsize[t.sizeindex]];
    6. cout << "请先输入10个数" << endl;
    7. for (int i = 0; i < hashsize[t.sizeindex]; ++i) {
    8. t.isfull[i] = false;
    9. }
    10. for (int i = 0; i < 10; ++i) {
    11. int temp;
    12. cin >> temp;
    13. insertHash(t,temp,hashsize);
    14. //print(t, hashsize);
    15. }
    16. print(t,hashsize);
    17. cout << "输入需要查找的数:" << endl;
    18. int key;
    19. cin >> key;
    20. int p;
    21. int c = 0;
    22. if (searchHash(t, key,p,c, hashsize)) {
    23. cout << "查找成功" << endl;
    24. cout << "为第" << p+1 << "个元素" << endl;
    25. }
    26. else {
    27. cout << "查找失败" << endl;
    28. }
    29. cout << "输入需要删除的数:" << endl;
    30. cin >> key;
    31. if (DeleteHash(t, key, hashsize)) {
    32. cout << "删除成功,删除后的结果:" << endl;
    33. print(t, hashsize);
    34. }
    35. else {
    36. cout << "删除失败" << endl;
    37. }
    38. system("pause");
    39. return 0;

    }

输入:

  1. 12 67 56 16 25 37 22 29 15 47
  2. 16
  3. 15

输出:
这里写图片描述

3、二次探测的实现

对于二次探测,其实它和线性探测的插入删除代码都是一样的,只是查找过程中单位的移动量不同,所以我们只要修改对应的查找函数就可以了,修改成如下:

  1. //查找对应的关键字
  2. bool searchHash(Hash t, Keytype k, int & p,int &c,int * hashsize) {
  3. p = k%hashsize[t.sizeindex];
  4. while (t.isfull[p] && t.elem[p] != k && c < hashsize[t.sizeindex]-1) {
  5. //++c;
  6. //二次探测和线性探测的区别
  7. if (c == 0) {
  8. c=1;
  9. p = (k + c) % hashsize[t.sizeindex];
  10. }
  11. else if (c > 0) {
  12. c = -c;
  13. p = (k - c*c) % hashsize[t.sizeindex];
  14. }
  15. else if (c < 0) {
  16. c = -c + 1;
  17. p = (k + c*c) % hashsize[t.sizeindex];
  18. }
  19. //继续往下寻找下一个散列结点
  20. }
  21. if (t.elem[p] == k) {
  22. return true;
  23. }
  24. return false;
  25. }

输入:

  1. 12 67 56 16 25 37 22 29 15 47
  2. 67
  3. 12

输出:
这里写图片描述

4、链地址法的实现

  • List.h文件的代码

    pragma once

    /**/
    / 程序作者:Willam /
    / 程序完成时间:2017/3/29 /
    / 有任何问题请联系:2930526477@qq.com /
    /**/
    //@尽量写出完美的程序

  1. //#pragma once是一个比较常用的C/C++杂注,
  2. //只要在头文件的最开始加入这条杂注,
  3. //就能够保证头文件只被编译一次。
  4. #include<iostream>
  5. using namespace std;
  6. typedef int Keytype;
  7. struct Node {
  8. Keytype data; //每个结点的值
  9. Node * next; //下一个结点
  10. Node() {
  11. next = NULL;
  12. }
  13. };
  14. //每次都是取质数最接近的质数
  15. struct Hash {
  16. Node * elem; //头结点链表
  17. int sizeindex;
  18. };
  19. bool searchHash(Hash t, Keytype k, Node* & p, Node * & pre, int * hashsize);
  20. bool insertHash(Hash & t, Keytype k, int * hashsize);
  21. bool DeleteHash(Hash & t, Keytype k, int * hashsize);
  22. void print(Hash t, int * hashsize);
  • List.cpp文件的代码

    include”List.h”

    bool searchHash(Hash t, Keytype k, Node & p, Node & pre, int * hashsize) {

    1. int index = k%hashsize[t.sizeindex];
    2. Node * head = t.elem[index].next;
    3. pre = NULL;
    4. while (head)
    5. {

    //变量整个结点

    1. p = head;
    2. if (head->data == k) {
    3. return true;
    4. }
    5. pre = head;
    6. head = head->next;
    7. }
    8. return false;

    }

  1. //插入
  2. bool insertHash(Hash & t, Keytype k, int * hashsize) {
  3. Node * p;
  4. Node * pre;
  5. if (searchHash(t, k, p,pre, hashsize)) {
  6. return false;
  7. }
  8. else {
  9. Node * s = new Node;
  10. s->data = k;
  11. if (pre == NULL) {
  12. int index = k%hashsize[t.sizeindex];
  13. t.elem[index].next = s;
  14. return true;
  15. }
  16. p->next = s;
  17. }
  18. return true;
  19. }
  20. //删除结点
  21. bool DeleteHash(Hash & t, Keytype k, int * hashsize) {
  22. Node * p;
  23. Node * pre;
  24. if (!searchHash(t, k, p,pre,hashsize)) {
  25. return false;
  26. }
  27. else {
  28. if (pre == NULL) {
  29. int index = k%hashsize[t.sizeindex];
  30. t.elem[index].next =p->next;
  31. return true;
  32. }
  33. else {
  34. pre->next = p->next;
  35. delete p;
  36. }
  37. }
  38. return true;
  39. }
  40. void print(Hash t, int * hashsize) {
  41. Node * p;
  42. for (int i = 0; i < hashsize[t.sizeindex]; ++i) {
  43. cout << i << " ";
  44. p = t.elem[i].next;
  45. while (p) {
  46. cout << p->data << " ";
  47. p = p->next;
  48. }
  49. cout << "^" << endl;
  50. }
  51. }
  • main.cpp文件的代码

    include”list.h”

    int hashsize[]={ 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107,
    109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223,
    227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337,
    347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457,
    461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593,
    599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719,
    727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857,
    859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997 };
    int main() {

    1. Hash t;
    2. t.sizeindex = 0;
    3. t.elem = new Node[hashsize[t.sizeindex]];
    4. cout << "请先输入10个数" << endl;
    5. for (int i = 0; i < hashsize[t.sizeindex]; ++i) {
    6. t.elem[i].next = NULL;
    7. }
    8. for (int i = 0; i < 10; ++i) {
    9. int temp;
    10. cin >> temp;
    11. insertHash(t,temp,hashsize);
    12. //print(t, hashsize);
    13. }
    14. print(t,hashsize);
  1. cout << "输入需要查找的数:" << endl;
  2. int key;
  3. cin >> key;
  4. Node *p;
  5. Node *pre;
  6. int c = 0;
  7. if (searchHash(t, key,p,pre, hashsize)) {
  8. cout << "查找成功" << endl;
  9. cout << p->data << endl;
  10. }
  11. else {
  12. cout << "查找失败" << endl;
  13. }
  14. cout << "输入需要删除的数:" << endl;
  15. cin >> key;
  16. if (DeleteHash(t, key, hashsize)) {
  17. cout << "删除成功,删除后的结果:" << endl;
  18. print(t, hashsize);
  19. }
  20. else {
  21. cout << "删除失败" << endl;
  22. }
  23. system("pause");
  24. return 0;
  25. }

输入:

  1. 12 67 56 16 25 37 22 29 15 47
  2. 29
  3. 29

输出:
这里写图片描述

发表评论

表情:
评论列表 (有 0 条评论,283人围观)

还没有评论,来说两句吧...

相关阅读

    相关 详解查找

    哈希表查找 定义 基本概念 实现方法 1、定义 > 哈希表查找又叫散列表查找,通过查找关键字不需要比较就可以获得需要记录的存储位置,它是通过在记

    相关 查找

    引入哈希表 前面查找方法共同特点:通过将关键字值与给定值比较,来确定位置。效率取决比较次数。 理想的方法是:不需要比较,根据给定值能直接定位记录的存储位置。 这样,

    相关 实现构造和查找算法

    实现哈希表构造和查找算法 实现哈希表构造和查找算法 使用的是除留余数法构造哈希函数,这里我用了两种方法解决冲突: 1. 一次探测再散列; 2. 二次探测再散列解决