定位式查找---哈希表
2016-04-30 11:13
204 查看
哈希查找
查找的三种主要形式1. 线性查找
2. 树形查找
3. 定位式查找
今天来讨论定位式查找—-哈希查找
哈希查找的主要思想:
通过一个特定的哈希函数对用户插入的内容进行计算得到一个结果,把用户输入的内容存入到这个结果所对应的地址处。当取值查找时同理,也是先进行哈希函数的计算,计算出结果去相应位置取出元素。
要讨论得问题
1. 哈希函数的构建
2. 如何解决冲突的问题(冲突就是两个不同的元素,但是经过计算得到了相同的哈希值)
3. 装填因子的问题(当前表中数据量 除以 当前表的大小 因子越小 冲突几率越小)
哈希函数构建的五种方法
1. 数学分析法:对于那种已知的关键字集合,可以对这个关键字进行分析判断那几位是均匀有规律分布的,就是用这几位来充当当前的数值的hash值,使用频率较少。
2. 平方求和法:对当前字串转化为Unicode值,并求出这个值的平方,去平方值中间的几位为当前数字的hash值,具体取几位要取决于当前哈希表的大小。
3. 分段求和法:根据当前哈希表的位数把所要插入的数值分成若干段,把若干段进行相加,舍去调最高位结果就是这个值的哈希值。
4. 整数求余法: 用当前这个字串除以最贴近这个字串的最大素数,求出的余数结果则为这个数值的hash值
5. 伪随机法:通过调用函数random求出随机的hash位置,这个使用频率也不高。
解决冲突的四种方法:
1.开放地址法:当出现冲突的时候,对这个冲突的hash值进行线性探测法或二次探测法,或伪探测法,顾名思义就是让这个hash值在加上一些数值再次进行判断看是否还冲突,如果还是冲突的话那么就再次的进行探测处理。
2. 在哈希法:在构建哈希函数的时候会构建若干个,但是执行的时候只执行一个,当执行的这个hash出现了冲突的时候,使用下一个哈希函数,知道没有冲突为止。
3. 链地址法:当出现冲突的时候照样往里面存储,以一种链式的形态进行存储,查询的时候找到这个链对这个链进行遍历检索。
4. 建立公共溢出区:特别划分出一个区域,当出现冲突的时候一律存储到这个公共溢出的区域。
性能问题:
要结合使用的构建哈希的函数以及哈希的冲突方法的选择在加上装填因子的判断才能判断出当前检索所需要的时间消耗。需要注意的是哈希查找并非简单的定位式查找。它的底层也用到了许多计算甚至遍历的方法。
代码:采用的是平方取中法构建哈希函数,开放地址法线性探测法进行解决冲突。
package 哈希法; /* * --------------Super 腾------------------ */ public class HashSearch { private static Object[] hash = new Object[100];//哈希表初始值为10个单位 public static void main(String[] args){ //插入数据存入哈希表中 String a = "abc"; String b = "def"; String c = "ghi"; String d = "jkl"; String e = "mno"; String f = "pqr"; String g = "stu"; String h = "vwx"; String i = "yz"; InsertHash(a); InsertHash(b); InsertHash(c); InsertHash(d); InsertHash(e); InsertHash(f); InsertHash(g); InsertHash(h); InsertHash(i); //定位式查找某一特定元素 int result = hashSearch("mno"); System.out.println("您输入的字符串为:mno"); System.out.println("当前在哈希表中的索引为:"+result); System.out.println("哈希表中索引为"+"'"+result+"'"+"处的字符串为"+hash[result]); } //建立hash表 public static void InsertHash(String data){ int index = hashFunction(data); //把取中当做哈希表中索引 if(hash[index] == null){ hash[index] = data; }else{ solveClash(index,data); } } //平方取中法 public static int hashFunction(String data){ //把字符串转化为字符用来求和之后进行平方运算 char[] d = data.toCharArray(); int temp = 0; for(int i=0;i<d.length;i++){ temp += (int)d[i]; } temp = temp*temp; //对平方的数值进行取中 int index = 0; String s = String.valueOf(temp); //取的整数的中间两位 借助了字符串下面的方法 index += Integer.parseInt(String.valueOf(s.charAt(s.length()/2-1)))*10; index += Integer.parseInt(String.valueOf(s.charAt(s.length()/2))); return index; } //解决插入冲突的方法 public static void solveClash(int index,String data){ //进行线性开放地址法解决冲突 for(int i=1;index+i<100;i++){ if(hash[index+i] == null){ hash[index+i] = data; break; } } } //通过hash算法定位式查找元素 public static int hashSearch(String data){ int index = hashFunction(data); return index; } }
结果
相关文章推荐
- 23种设计模式
- MongoDB入门教程(二)
- 23种设计模式
- GSL - GNU Scientific Library 在 windows 上的使用
- Redis与Memcached的区别
- IDE 下未提交代码本地被覆盖如何恢复
- bsoj 3733 【模拟试题】打印文章(hdu3507)
- 事件总线 EventBus
- 20145212 《Java程序设计》第9周学习总结
- mysql中使用正则表达式查询
- 58. Android一些开发习惯总结
- button圆角
- button圆角
- nagios 笔记
- php数组分页实现方法
- jQuery 实现Ajax
- Caffe 深度学习框架上手教程
- HTML框架
- C++基础实践指导(上)
- struts2中form提交到action中的中文参数乱码问题解决办法(包括取中文路径)