zoukankan      html  css  js  c++  java
  • 算法:哈希表格(Hash Table)

    背景

    Java 和 .Net 平台都有一个所有引用类型都会间接或直接继承的类型:Object,这个类型提供最基本的相等性比较算法和哈希算法,很多书上都给出了在重写这两个算法的时候的主意事项,其中大多数主意事项都和哈希表有关。

    《CLR VIA C#》的作者觉得将哈希算法放到 Object 不是很适合,我也有这种感觉,每次重写相等性比较算法都要重新哈希算法,非常不爽,我就没打算将其用到哈希表中作为键使用。

    哈希表

    定义

    使用哈希算法将 A 数值空间(键)映射到 B 数值空间(存储),如下:

    A -> 0

    B -> 1

    C -> 2

    D -> 3

    B 数值空间的查询速度要求非常快,毫无疑问就是数值了。

    冲突

    数组的大小是固定,当出现冲突(两个键映射为同一个数值了)的时候如何处理呢?有两种策略:

    • 在数组中按照一定的算法继续探测其它地址。
    • 在数组的每个元素存储的都是链表,冲突的元素会被插入到链表中。

    实现

    链表节点

    1         class Node<TKey, TValue>
    2         {
    3             public TKey Key { get; set; }
    4 
    5             public TValue Value { get; set; }
    6 
    7             public Node<TKey, TValue> Next { get; set; }
    8         }

    链表

     1         class LinkedList<TKey, TValue>
     2         {
     3             public Node<TKey, TValue> First { get; set; }
     4 
     5             public void Insert(TKey key, TValue value)
     6             {
     7                 if (this.Contains(key))
     8                 {
     9                     throw new InvalidOperationException("不能插入重复的键");
    10                 }
    11 
    12                 var node = new Node<TKey, TValue> { Key = key, Value = value };
    13                 node.Next = this.First;
    14                 this.First = node;
    15             }
    16 
    17             public void Delete(TKey key)
    18             {
    19                 Node<TKey, TValue> parent;
    20                 Node<TKey, TValue> node;
    21 
    22                 if (!this.Find(key, out   parent, out  node))
    23                 {
    24                     throw new InvalidOperationException("不存在指定的键");
    25                 }
    26 
    27                 if (parent == null)
    28                 {
    29                     this.First = null;
    30                 }
    31                 else
    32                 {
    33                     parent.Next = node.Next;
    34                 }
    35             }
    36 
    37             public bool Contains(TKey key)
    38             {
    39                 Node<TKey, TValue> parent;
    40                 Node<TKey, TValue> node;
    41 
    42                 return this.Find(key, out   parent, out  node);
    43             }
    44 
    45             public bool Find(TKey key, out Node<TKey, TValue> node)
    46             {
    47                 Node<TKey, TValue> parent;
    48 
    49                 return this.Find(key, out  parent, out  node);
    50             }
    51 
    52             public bool Find(TKey key, out Node<TKey, TValue> parent, out Node<TKey, TValue> node)
    53             {
    54                 parent = null;
    55                 node = this.First;
    56 
    57                 while (node != null)
    58                 {
    59                     if (node.Key.Equals(key))
    60                     {
    61                         return true;
    62                     }
    63 
    64                     parent = node;
    65                     node = node.Next;
    66                 }
    67 
    68                 return false;
    69             }
    70         }

    哈希表

     1         class HashTable<TKey, TValue>
     2         {
     3             private LinkedList<TKey, TValue>[] _items;
     4 
     5             public HashTable(int size)
     6             {
     7                 _items = new LinkedList<TKey, TValue>[size];
     8             }
     9 
    10             public void Insert(TKey key, TValue value)
    11             {
    12                 var index = this.HashToIndex(key);
    13                 if (_items[index] == null)
    14                 {
    15                     _items[index] = new LinkedList<TKey, TValue>();
    16                 }
    17 
    18                 _items[index].Insert(key, value);
    19             }
    20 
    21             public void Delete(TKey key)
    22             {
    23                 var index = this.HashToIndex(key);
    24                 if (_items[index] == null)
    25                 {
    26                     throw new InvalidOperationException("不存在指定的键");
    27                 }
    28 
    29                 _items[index].Delete(key);
    30             }
    31 
    32             public bool Find(TKey key, out TValue value)
    33             {
    34                 value = default(TValue);
    35 
    36                 var index = this.HashToIndex(key);
    37                 if (_items[index] == null)
    38                 {
    39                     return false;
    40                 }
    41 
    42                 Node<TKey, TValue> node;
    43                 var finded = _items[index].Find(key, out  node);
    44                 if (!finded)
    45                 {
    46                     return false;
    47                 }
    48                 else
    49                 {
    50                     value = node.Value;
    51                 }
    52 
    53                 return true;
    54             }
    55 
    56             private int HashToIndex(TKey key)
    57             {
    58                 return key.GetHashCode() % _items.Length;
    59             }
    60         }

    备注

    哈希算法、负载因子、自动扩容都是需要考虑的,这里就不多说了。 

  • 相关阅读:
    外面下雨了,凉快了
    无聊,听说wow五区开放了,注册个人物去玩玩
    草原游记二大青山上
    终于拿到钥匙了
    刚看到一个论坛的帖子,一位大哥说到真是话糙理不糙,佩服
    草原随感录武川印象
    第一次网上买点卡
    看到小说<搜神新记>里面巨搞笑的一段,是共工和太章打完架后,把事先被昏迷的人叫醒的事情
    昨天晚上很生气很生气。。。。
    感于"一生所爱"
  • 原文地址:https://www.cnblogs.com/happyframework/p/3490707.html
Copyright © 2011-2022 走看看