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

  算法流程:

  1)用给定的哈希函数构造哈希表;

  2)根据选择的冲突处理方法解决地址冲突;常见的解决冲突的方法:拉链法和线性探测法。

  3)在哈希表的基础上执行哈希查找。

  哈希表是一个在时间和空间上做出权衡的经典例子。如果没有内存限制,那么可以直接将键作为数组的索引。那么所有的查找时间复杂度为O(1);如果没有时间限制,那么我们可以使用无序数组并进行顺序查找,这样只需要很少的内存。哈希表使用了适度的时间和空间来在这两个极端之间找到了平衡。只需要调整哈希函数算法即可在时间和空间上做出取舍。

  复杂度分析:

  单纯论查找复杂度:对于无冲突的Hash表而言,查找复杂度为O(1)(注意,在查找之前我们需要构建相应的Hash表)。

  Hash是一种典型以空间换时间的算法,比如原来一个长度为100的数组,对其查找,只需要遍历且匹配相应记录即可,从空间复杂度上来看,假如数组存储的是byte类型数据,那么该数组占用100byte空间。现在我们采用Hash算法,我们前面说的Hash必须有一个规则,约束键与存储位置的关系,那么就需要一个固定长度的hash表,此时,仍然是100byte的数组,假设我们需要的100byte用来记录键与位置的关系,那么总的空间为200byte,而且用于记录规则的表大小会根据规则,大小可能是不定的

  

哈希查找Java代码 哈希查找例题_寻址

哈希查找Java代码 哈希查找例题_复杂度_02

1 public class HashSearch {
 2 
 3     /****
 4      * Hash查找
 5      * @param hash
 6      * @param hashLength
 7      * @param key
 8      * @return
 9      */
10     public static int searchHash(int[] hash, int hashLength, int key) {
11         // 哈希函数
12         int hashAddress = key % hashLength;
13 
14         // 指定hashAdrress对应值存在但不是关键值,则用开放寻址法解决
15         while (hash[hashAddress] != 0 && hash[hashAddress] != key) {
16             hashAddress = (++hashAddress) % hashLength;
17         }
18 
19         // 查找到了开放单元,表示查找失败
20         if (hash[hashAddress] == 0)
21             return -1;
22         return hashAddress;
23 
24     }
25 
26     /***
27      * 数据插入Hash表
28      * 
29      * @param hash
30      *            哈希表
31      * @param hashLength
32      * @param data
33      */
34     public static void insertHash(int[] hash, int hashLength, int data) {
35         // 哈希函数
36         int hashAddress = data % hashLength;
37 
38         // 如果key存在,则说明已经被别人占用,此时必须解决冲突
39         while (hash[hashAddress] != 0) {
40             // 用开放寻址法找到
41             hashAddress = (++hashAddress) % hashLength;
42         }
43 
44         // 将data存入字典中
45         hash[hashAddress] = data;
46     }
47 }

View Code