zoukankan      html  css  js  c++  java
  • Hash

    一个对象或者内容,输入到一个算法执行计算得出一个唯一的值。
    1. 这个过程我们称为映射;也叫hash
    2. 这个算法我们称为hash算法或者hash函数该算法是单向不可逆的,即无法通过hash值反向推导出原对象。
    3. 计算出来的唯一值我们称为hash值
    4. 计算出来的hash值在一个环境下是一个固定长度的值。通常算法是将一个很大的输入映射为一个很小的固定长度的值。否则难以保存。
    计算出来的hash值可能会重复,这取决于hash函数/算法的可用性和准确性。理论上,这个值必需是唯一的,但是目前研发出来的hash算法都多多少少会出现重复的情况,只是概率极低。这种重复我们称为“hash碰撞”。
     
    计算出来的值我们可以称之为key,一个key映射到一个地址,该地址保存该对象或者内容。通过该key可以直接访问到对应的对象。
    而保存这些对象的结构我们称为hash表,或者散列表
    通常的实现是,使用一个数组来保存这些key,而使用另外一个数组来保存对应的对象。而这些key通过某些方法保存与之对应的数组索引或者地址。
    这种结构与下述场景很相似:
    现在有很多房屋,每个房屋通过某种方法确定一个唯一的编号与之对应。这些房屋的钥匙存在一个箱子,箱子标有房屋的编号。想进入房屋的方法是:拿到该房屋的编号,然后去对应的箱子去拿到该该房屋的钥匙。
     
    所以Hash表的访问速度非常快,总是O(1)。
     
    应用场景
    hash可以使用在如下场景:
    1. 加密:其单向性决定的;
    2. 数据验证:其结果唯一性决定的;
    3. 海量数据:海量数据的关键问题不是存储空间,而是查找时间。hash表支持随机访问。也就是因为这个特性,目前市面上的许多高效的存储引擎都使用hash表来保存数据。传统的RMDB是无法做到的。
     
    Hash碰撞
    hash碰撞也叫hash冲突。这是hash表最关键的,也是设计hash算法最难的。
    解决hash碰撞的方法有:
    1. 开放寻址
    2. 链表法
     
    Hash表和二叉树

    哈希表有以下几个突出的缺点:

    1. 当更多的数插入时,哈希表冲突的可能性就更大。对于冲突,哈希表通常有两种解决方案:第一种是线性探索,相当于在冲突的槽后建立一个单链表,这种情况下,插入和查找以及删除操作消耗的时间会达到O(n),且该哈希表需要更多的空间进行储存。第二种方法是开放寻址,他不需要更多的空间,但是在最坏的情况下(例如所有输入数据都被map到了一个index上)的时间复杂度也会达到O(n)。

    2. 所以,在决定建立哈希表之前,最好可以估计输入的数据的size。否则,resize哈希表的过程将会是一个非常消耗时间的过程。例如,如果现在你的哈希表的长度是100,但是现在有第101个数要插入。这时,不仅哈希表的长度可能要扩展到150,且扩展之后所有的数都需要重新rehash。

    3. 哈希表中的元素是没有被排序的。然而,有些情况下,我们希望储存的数据是有序的。

    二叉树

    1. 二叉树不会有冲突(collision),这意味着我们能够保证二叉树的插入和查找操作一直都是O(log(n))的时间复杂度。

    2. 二叉树的空间占用跟输入的输入数据一致。所以我们不需要为二叉树预先分配固定的空间。所以,你也不需要预先知道输入数据的size。

    3. 所有的元素在树中是排序好的。

     
  • 相关阅读:
    MongoDB小结25
    MongoDB小结24
    MongoDB小结23
    MongoDB小结22
    MongoDB小结21
    MongoDB小结20
    MongoDB小结19
    MongoDB小结18
    hdu 4606 Occupy Cities
    hdu 4610 Cards
  • 原文地址:https://www.cnblogs.com/chorulex/p/13186317.html
Copyright © 2011-2022 走看看