一、二分法
算法:当数据量很大适宜采用该方法。采用二分法查找时,数据需是排好序的。
时间复杂度:O(logN)
java代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | public class BubbleTest { public static int binary( int [] array, int value) { int low = 0 ; int high = array.length - 1 ; while (low <= high) { int middle = (low + high) / 2 ; if (value == array[middle]) { return middle; } if (value > array[middle]) { low = middle + 1 ; } if (value < array[middle]) { high = middle - 1 ; } } return - 1 ; } public static void main(String[] args) { int [] a = { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 }; int value = binary(a, 9 ); System.out.println(value); } } |
二、hash表
哈希查找是通过计算
数据元素
的存储地址进行查找的一种方法。不同于二分法,该方法不用对元素之间进行比较就能直接计算出记录的存储地址。
首先介绍几个概念。
1.哈希函数h。用来构建键值k存储地址的函数。即输入一个键值,带入该函数,输出的函数值h(k)即作为该键值的存储地址。常见的哈希函数构造方法有直接定址法、数字分析法、平方取中法等等。
2.冲突。对于不同的键值k1和k2,h(k1)=h(k2),具有相同的存储地址这一情况被称为冲突。常见的冲突处理方法有:开放定址法、链地址法(链地址法就是把所有哈希地址相同的记录都存放在链表的同一结点延伸出来的线性表中,不解决冲突)。本文重点讲解开放定址法。开放定址法就是当冲突发生时,使用某种方法(如线性探测法、再散列探测法等)在hash表中形成一个探查序列,沿着此序列逐个地址探查,直到找到一个开放的地址(也就是空地址),再讲发生冲突的键值放到该地址中。
3.线性探测法。若地址单元d发生冲突,则依次探查d+1,d+2…,m-1,0,1,…..,d-1(m为表长)。找到开放位置(空位置),则插入。一般来说,如果只用线性探测法,容易产生堆积现象,所谓的堆积现象就是用线性探查法解决冲突时,当表中i,i+1,…,i+k的位置上已有结点时,一个散列地址为i,i+1,…,i+k+1的结点都将插入在位置i+k+1上。
(
参考链接:
http://student.zjzk.cn/course_ware/data_structure/web/chazhao/chazhao9.4.3.2.htm
)
解决堆积现象的方法就是前文中提到的再散列探测法,再散列探测法的核心思想是当h1(k1)=h1(k2)=d时,再构造一个h2,使得h2(k1)<>h2(k2)
OK,基础概念铺垫完毕,接下来通过例子帮助大家深入理解,一起来看看~
比如对于关键字集合{13,22,34,55,2}
设定哈希函数H(key)=key MOD 11, 并且使用线性探测法,则生成的哈希表如下所示:
0 | 1 | 2 | 3 | 4 | |
22 | 34 | 13 | 55 | 2 |
其中,13 MOD 11= 2,22 MOD 11= 0,34 MOD 11= 1,55 MOD 11= 0,2 MOD 11= 2.显然有两个冲突(有两对h(k)相等),则按照上面介绍的线性探测法,解决冲突。
再散列探测法跟线性探测法相似,只是采用的是结合不同的哈希函数构造方法再算一遍,构造不同的地址,在此不做赘述。