• hash表简单实现


    查找算法大总结: http://www.cnblogs.com/maybe2030/p/4715035.html#_label6

    常用的hash函数: http://blog.csdn.net/mycomputerxiaomei/article/details/7641221

    什么是哈希表(Hash)?

      我们使用一个下标范围比较大的数组来存储元素。可以设计一个函数(哈希函数, 也叫做散列函数),使得每个元素的关键字都与一个函数值(即数组下标)相对应,于是用这个数组单元来存储这个元素;也可以简单的理解为,按照关键字为每一个元素"分类",然后将这个元素存储在相应"类"所对应的地方。但是,不能够保证每个元素的关键字与函数值是一一对应的,因此极有可能出现对于不同的元素,却计算出了相同的函数值,这样就产生了"冲突",换句话说,就是把不同的元素分在了相同的"类"之中。后面我们将看到一种解决"冲突"的简便做法。
      总的来说,"直接定址"与"解决冲突"是哈希表的两大特点。

      什么是哈希函数?

      哈希函数的规则是:通过某种转换关系,使关键字适度的分散到指定大小的的顺序结构中,越分散,则以后查找的时间复杂度越小,空间复杂度越高。

      算法思想:哈希的思路很简单,如果所有的键都是整数,那么就可以使用一个简单的无序数组来实现:将键作为索引,值即为其对应的值,这样就可以快速访问任意键的值。这是对于简单的键的情况,我们将其扩展到可以处理更加复杂的类型的键。

      算法流程:

      1)用给定的哈希函数构造哈希表;
      2)根据选择的冲突处理方法解决地址冲突;
        常见的解决冲突的方法:拉链法和线性探测法。详细的介绍可以参见:浅谈算法和数据结构: 十一 哈希表
      3)在哈希表的基础上执行哈希查找。
      哈希表是一个在时间和空间上做出权衡的经典例子。如果没有内存限制,那么可以直接将键作为数组的索引。那么所有的查找时间复杂度为O(1);如果没有时间限制,那么我们可以使用无序数组并进行顺序查找,这样只需要很少的内存。哈希表使用了适度的时间和空间来在这两个极端之间找到了平衡。只需要调整哈希函数算法即可在时间和空间上做出取舍。

    实现:

    定义hash:

     1 typedef struct node
     2 {
     3     int value;
     4     struct node *next;
     5 }NODE; 
     6 
     7 typedef struct hash
     8 {
     9     int size;
    10     NODE **list;
    11 }HASH;

    初始化hash:

     1 HASH *HashInit(int size)
     2 {
     3     if (size <= 0)
     4         return NULL;
     5     HASH *hash = (HASH*)malloc(sizeof(HASH));
     6     if (NULL == hash)
     7         return NULL;
     8     hash->size = size;
     9     hash->list = (NODE**)malloc(sizeof(NODE*) * hash->size);
    10     if (NULL == hash->list)
    11     {
    12         free(hash);
    13         hash = NULL;
    14         return NULL;
    15     }
    16     int i;
    17     for (i = 0; i < size; i++)
    18     {
    19         hash->list[i] = (NODE*)malloc(sizeof(NODE));
    20         hash->list[i]->next = NULL;
    21     }
    22     return hash;
    23 }

    hash查找:

    NODE *HashFind(HASH *hash, int key)
    {
        NODE *list = hash->list[HashFun(key, hash->size)];
        NODE *node = list->next;
        for (;NULL != node && node->value != key; node = node->next);
        return node;
    }

    hash插入:

    void HashInstert(HASH* hash, int key)
    {
        if (NULL != HashFind(hash, key))
            return;
        NODE *node = (NODE*)malloc(sizeof(NODE));
        if (NULL == node)
            return;
        NODE *list = hash->list[HashFun(key, hash->size)];
        node->value = key;
        node->next = list->next;
        list->next = node;
    }
  • 相关阅读:
    详细讲解mysql 主从复制原理
    Golang语言快速上手到综合实战笔记(Go语言、Beego框架、高并发聊天室、爬虫)
    每个人都应该知道的25个Git命令
    docker 记录
    MySQL主从复制数据同步,常见问题总结
    详解mysql 主从复制原理
    算法系列15天速成——第十天 栈
    算法系列15天速成——第二天 七大经典排序【中】
    算法系列15天速成——第一天 七大经典排序【上】
    算法系列15天速成——第四天 五大经典查找【上】
  • 原文地址:https://www.cnblogs.com/dapaitou2006/p/6644921.html
Copyright © 2020-2023  润新知