• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

数据结构--哈希表代码实现

武飞扬头像
鱼非愚
帮助1

1、直接定制法
哈希函数为关键字的线性函数如 H(key)=a*key b
这种构造方法比较简便,均匀,但是有很大限制,仅限于地址大小=关键字集合的情况

产生hash冲突后在存储数据后面加一个指针,指向后面冲突的数据

 2、查找过程和造表过程一致,假设采用开放定址法处理冲突,则查找过程为:
对于给定的key,计算hash地址index = H(key)
如果数组arr【index】的值为空 则查找不成功
如果数组arr【index】== key 则查找成功
否则 使用冲突解决方法求下一个地址,直到arr【index】== key或者 arr【index】==null
3、决定hash表查找的ASL因素:
1)选用的hash函数
2)选用的处理冲突的方法
3)hash表的饱和度,装载因子 α=n/m(n表示实际装载数据长度 m为表长)
一般情况,假设hash函数是均匀的,则在讨论ASL时可以不考虑它的因素
hash表的ASL是处理冲突方法和装载因子的函数
4、代码实现:

  1.  
    #ifndef _HASH_H_
  2.  
    #define _HASH_H_
  3.  
     
  4.  
    #include <stdio.h>
  5.  
    #include <string.h>
  6.  
    #include <stdlib.h>
  7.  
     
  8.  
    #define N 13 //hash表顺序表部分数组元素个数
  9.  
     
  10.  
    typedef int data_t;
  11.  
     
  12.  
    //数据节点
  13.  
    struct link
  14.  
    {
  15.  
    data_t data;
  16.  
    struct link *next;
  17.  
    };
  18.  
     
  19.  
    typedef struct link LINK;
  20.  
     
  21.  
    //hash表顺序表部分(保存数据节点所构成的链表的头节点)
  22.  
    struct hash
  23.  
    {
  24.  
    LINK *hp[N];
  25.  
    };
  26.  
     
  27.  
    typedef struct hash HASH;
  28.  
     
  29.  
    HASH *CreateHash();
  30.  
    void InsertHash(HASH *p,data_t num);
  31.  
    void ShowHash(HASH *p);
  32.  
    LINK * FindHash(HASH *p,data_t num);
  33.  
    void UpdateHash(HASH *p,data_t old_num,data_t new_num);
  34.  
    void DeleteHash(HASH *p,data_t num);
  35.  
    HASH *DestoryHash(HASH *p);
  36.  
    #endif
学新通
  1.  
     
  2.  
    #include "hash.h"
  3.  
     
  4.  
    HASH *CreateHash()
  5.  
    {
  6.  
    HASH *p = (HASH *)malloc(sizeof(HASH));
  7.  
    if(NULL == p)
  8.  
    {
  9.  
    perror("hash表顺序表部分申请空间失败");
  10.  
    return p;
  11.  
    }
  12.  
    memset(p,0,sizeof(HASH));
  13.  
    return p;
  14.  
    }
  15.  
     
  16.  
    //创建新节点
  17.  
    LINK *CreateNode(data_t num)
  18.  
    {
  19.  
    LINK *node = (LINK *)malloc(sizeof(LINK));
  20.  
    if(NULL == node)
  21.  
    {
  22.  
    perror("新节点申请空间失败");
  23.  
    return node;
  24.  
    }
  25.  
    memset(node,0,sizeof(LINK));
  26.  
    node->data = num;
  27.  
    return node;
  28.  
    }
  29.  
     
  30.  
    //hash函数:计算插入数据的位置,建立记录与地址的对应关系
  31.  
    int HashFun(data_t num)
  32.  
    {
  33.  
    return num % N;
  34.  
    }
  35.  
     
  36.  
    void InsertHash(HASH *p,data_t num)
  37.  
    {
  38.  
    //1、判定入參
  39.  
    if(NULL == p)
  40.  
    {
  41.  
    perror("hash表不能存在");
  42.  
    return;
  43.  
    }
  44.  
     
  45.  
    //2、创建新节点保留插入数据
  46.  
    LINK *new_node = CreateNode(num);
  47.  
    if(NULL == new_node)
  48.  
    {
  49.  
    perror("新节点创建失败");
  50.  
    return;
  51.  
    }
  52.  
     
  53.  
    //3、通过hash函数计算插入位置 ==》算法时间复杂度是否接近O(C)重要指标
  54.  
    int pos = HashFun(new_node->data);
  55.  
     
  56.  
    //4、根据hash函数计算的地址,将数据节点插入到hash表中
  57.  
    if(p->hp[pos] == NULL)//判定pos行没有数据,则新节点就可以直接插入
  58.  
    {
  59.  
    p->hp[pos] = new_node;
  60.  
    }
  61.  
    else//判定pos行有数据,则新节点去寻找合适的插入位置
  62.  
    {
  63.  
    //如果if后为0,则执行按照大小排序插入新节点;如果为1,则执行正常的简易hash表的插入操作
  64.  
    #if 1
  65.  
    LINK *tmp = p->hp[pos];
  66.  
    while(NULL != tmp->next)
  67.  
    {
  68.  
    tmp = tmp->next;
  69.  
    }
  70.  
     
  71.  
    tmp->next = new_node;
  72.  
    #else
  73.  
    if(p->hp[pos]->data >= new_node->data)//因为第一个数据节点已经大于插入的数据的特殊处理
  74.  
    {
  75.  
    new_node->next = p->hp[pos];
  76.  
    p->hp[pos] = new_node;
  77.  
    return;
  78.  
    }
  79.  
     
  80.  
    LINK *tmp = p->hp[pos];
  81.  
    while(tmp != NULL)//当找到当前表结尾处仍然没有找到合适插入位置,则将新节点直接接到尾节点后
  82.  
    {
  83.  
    if(tmp->data >= new_node->data)//查找到是插入数据将要插入的位置
  84.  
    {
  85.  
    break;
  86.  
    }
  87.  
    tmp = tmp->next;
  88.  
    }
  89.  
     
  90.  
    LINK *ntmp = p->hp[pos];
  91.  
    while(ntmp->next != tmp)//查找插入数据将要插入位置的前一个位置
  92.  
    {
  93.  
    ntmp = ntmp->next;
  94.  
    }
  95.  
     
  96.  
    tmp = ntmp;//为统一在最后使用tmp进行插入
  97.  
     
  98.  
    new_node->next = tmp->next;
  99.  
    tmp->next = new_node;
  100.  
    #endif
  101.  
    }
  102.  
    }
  103.  
     
  104.  
    void ShowHash(HASH *p)
  105.  
    {
  106.  
    //1、判定入參
  107.  
    if(NULL == p)
  108.  
    {
  109.  
    perror("hash表不能存在");
  110.  
    return;
  111.  
    }
  112.  
     
  113.  
    int i = 0;
  114.  
    for(i = 0;i < N;i )
  115.  
    {
  116.  
    printf("%-2d : ",i);
  117.  
    if(p->hp[i] == NULL)
  118.  
    {
  119.  
    printf("\n");
  120.  
    continue;
  121.  
    }
  122.  
    else
  123.  
    {
  124.  
    LINK *tmp = p->hp[i];
  125.  
    while(tmp != NULL)
  126.  
    {
  127.  
    printf("%d ",tmp->data);
  128.  
    tmp = tmp->next;
  129.  
    }
  130.  
    }
  131.  
    printf("\n");
  132.  
    }
  133.  
    }
  134.  
     
  135.  
    LINK * FindHash(HASH *p,data_t num)
  136.  
    {
  137.  
    //1、判定入參
  138.  
    if(NULL == p)
  139.  
    {
  140.  
    perror("hash表不能存在");
  141.  
    return NULL;
  142.  
    }
  143.  
     
  144.  
    //2、通过hash函数计算插入位置 ==》算法时间复杂度是否接近O(C)重要指标
  145.  
    int pos = HashFun(num);
  146.  
     
  147.  
    //3、根据hash函数计算的地址,查找num是否在hash表中
  148.  
    if(p->hp[pos] == NULL)//判定pos行没有数据,则查找失败
  149.  
    {
  150.  
    printf("该行没有数据,因此查找失败!\n");
  151.  
    return NULL;
  152.  
    }
  153.  
    else
  154.  
    {
  155.  
    LINK *tmp = p->hp[pos];
  156.  
    while(NULL != tmp)
  157.  
    {
  158.  
    if(tmp->data == num)
  159.  
    {
  160.  
    printf("find data = %d\n",tmp->data);
  161.  
    return tmp;
  162.  
    }
  163.  
    tmp = tmp->next;
  164.  
    }
  165.  
    }
  166.  
    printf("该hash表没有该数据,因此查找失败!\n");
  167.  
    return NULL;
  168.  
    }
  169.  
     
  170.  
    void UpdateHash(HASH *p,data_t old_num,data_t new_num)
  171.  
    {
  172.  
    //1、判定入參
  173.  
    if(NULL == p)
  174.  
    {
  175.  
    perror("hash表不能存在");
  176.  
    return;
  177.  
    }
  178.  
     
  179.  
    LINK * tmp = FindHash(p,old_num);
  180.  
    if(NULL == tmp)
  181.  
    {
  182.  
    return;
  183.  
    }
  184.  
     
  185.  
    tmp->data = new_num;
  186.  
    }
  187.  
     
  188.  
    void DeleteHash(HASH *p,data_t num)
  189.  
    {
  190.  
    //1、判定入參
  191.  
    if(NULL == p)
  192.  
    {
  193.  
    perror("hash表不能存在");
  194.  
    return;
  195.  
    }
  196.  
     
  197.  
    LINK * tmp = FindHash(p,num);
  198.  
    if(NULL == tmp)
  199.  
    {
  200.  
    return;
  201.  
    }
  202.  
     
  203.  
    //3、通过hash函数计算插入位置 ==》算法时间复杂度是否接近O(C)重要指标
  204.  
    int pos = HashFun(num);
  205.  
     
  206.  
    if(p->hp[pos] == tmp)//删除的数据节点为第一个数据节点
  207.  
    {
  208.  
    p->hp[pos] = tmp->next;
  209.  
    }
  210.  
    else//删除的数据节点不是第一个数据节点
  211.  
    {
  212.  
    LINK *ntmp = p->hp[pos];
  213.  
    while(ntmp->next != tmp)//查找删除数据将要插入位置的前一个位置
  214.  
    {
  215.  
    ntmp = ntmp->next;
  216.  
    }
  217.  
     
  218.  
    ntmp->next = tmp->next;
  219.  
    }
  220.  
     
  221.  
    free(tmp);
  222.  
    tmp = NULL;
  223.  
    }
  224.  
     
  225.  
    HASH *DestoryHash(HASH *p)
  226.  
    {
  227.  
    //1、判定入參
  228.  
    if(NULL == p)
  229.  
    {
  230.  
    perror("hash表不能存在");
  231.  
    return;
  232.  
    }
  233.  
     
  234.  
    //2、销毁所有数据链表
  235.  
    int i = 0;
  236.  
    for(i = 0;i < N;i )
  237.  
    {
  238.  
    if(p->hp[i] == NULL)
  239.  
    {
  240.  
    continue;
  241.  
    }
  242.  
    else
  243.  
    {
  244.  
    while(p->hp[i] != NULL)
  245.  
    {
  246.  
    LINK *tmp = p->hp[i];
  247.  
    p->hp[i] = tmp->next;
  248.  
    free(tmp);
  249.  
    tmp = NULL;
  250.  
    }
  251.  
    }
  252.  
    }
  253.  
    //3、销毁hash表的顺序表部分
  254.  
    free(p);
  255.  
    p = NULL;
  256.  
    return p;
  257.  
    }
学新通

main函数: 

  1.  
     
  2.  
    #include "hash.h"
  3.  
     
  4.  
    int main()
  5.  
    {
  6.  
    HASH *head = CreateHash();
  7.  
    if(NULL == head)
  8.  
    {
  9.  
    perror("hash表创建失败!");
  10.  
    return -1;
  11.  
    }
  12.  
    printf("hash表创建成功!\n");
  13.  
     
  14.  
    int k[12] = {23,34,14,38,46,16,68,15,7,31,26,20};
  15.  
    int i = 0;
  16.  
    for(i = 0;i < 12;i )
  17.  
    {
  18.  
    InsertHash(head,k[i]);
  19.  
    }
  20.  
     
  21.  
    printf("打印数据:\n");
  22.  
    ShowHash(head);
  23.  
     
  24.  
    //FindHash(head,17);
  25.  
    //UpdateHash(head,46,10000);
  26.  
    //DeleteHash(head,26);
  27.  
     
  28.  
    //printf("打印数据:\n");
  29.  
    //ShowHash(head);
  30.  
     
  31.  
    HASH *thead = DestoryHash(head);
  32.  
    printf("打印数据:\n");
  33.  
    ShowHash(thead);
  34.  
     
  35.  
    return 0;
  36.  
    }
学新通

Makefile: 

  1.  
     
  2.  
    TARGET=hash
  3.  
    CC=gcc
  4.  
    OBJS=main.c hash.c
  5.  
     
  6.  
    $(TARGET):$(OBJS)
  7.  
    $(CC) $^ -o $@ -g
  8.  
     
  9.  
     
  10.  
    clean:
  11.  
    rm *~
  12.  
    rm $(TARGET)
  13.  
     

运行结果: 

  1.  
    huqin@ubuntu:/mnt/hgfs/share/code/2021/mon11/week1/hash$ ./hash
  2.  
    hash表创建成功!
  3.  
    打印数据:
  4.  
    0 : 26
  5.  
    1 : 14
  6.  
    2 : 15
  7.  
    3 : 16 68
  8.  
    4 :
  9.  
    5 : 31
  10.  
    6 :
  11.  
    7 : 46 7 20
  12.  
    8 : 34
  13.  
    9 :
  14.  
    10 : 23
  15.  
    11 :
  16.  
    12 : 38
  17.  
    打印数据:
  18.  
    hash表不能存在: Success
学新通

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhhjhcfh
系列文章
更多 icon
同类精品
更多 icon
继续加载