经过一段时间的研究学习,对于Hash有了更深一步的了解和认识,下面谈谈一些基本概念及自己设计的一个MyHash的实现。
1、基本概念:
Hash,一般翻译做“散列”,也有直接音译为“哈希”。
哈希就是把任意长度的输入通过散列算法,变换成固定长度的输出,该输出就是散列值。
Hash主要用于信息安全领域中加密算法,把一些不同长度的信息转化成杂乱的128位编码,这些编码值叫哈希值。也可以说哈希就是找到一种数据内容和数据存放地址之间的映射关系。
哈希表就是一种根据关键码值直接进行访问的数据结构。
2、哈希表的优缺点:
那么为什么使用哈希表呢?它一定有特定的优点我们才会使用它。看看这个图表,相信大家就了解了吧~~
数组具有查找迅速但是对其进行插入删除操作较困难的特点,而链表容易插入删除但查找困难。。。是否有一种数据结构能够将两者的优点集合呢?哈希表就是一个两全其美的选择~~他是直接根据key值找到相应的存储位置,对其进行访问,插入删除操作类似于链表的相关操作。哈希表是基于快速存取的角度设计的,它的优点非常明显,存取速度能达到常量级O(1)
当然它也有一定的缺点:
1、使元素丧失了有序性
2、元素不能够紧密的排列,需要足够大的空间
3、两个或多个不同项被散列到同一位置是不可避免的
——冲突
【冲突:对不同的关键字可能得到同一散列地址 即key1≠key2,而f(key1)=f(key2) 】
v1.直接寻址法
v2.数字分析法
v3.平方取中法
v4.叠加法
v5.随机数法
v6.除留余数法
比较常用的是除留余数法,下面详细介绍一下此方法:
取关键字被某个不大于散列表表长m的数p除后所得的余数为散列地址
。
即 H(key) = key MOD p (p<=m)
例如: 给定一组关键字为: 12, 39, 18, 24, 33, 21
H(key) = key MOD 9 3 3 0 6 6 3
这里对P要有什么限制条件呢?
12, 39, 18, 24, 33, 21
若取 p=9, 则他们对应的哈希函数值将为:
3, 3, 0, 6, 6, 3
若取 P=18,则他们对应的哈希函数值将为12,3,0,6,15,3
若取p=24,则他们将对应的哈希函数值将为:
12,15,18,0,9,21
一般结论:选取的P较小,“冲突”的可能性较大
4、解决冲突的方法:
1、拉链法:即构造成数组链表的形式
2、在哈希法:设计两种甚至多种哈希函数
3、开放地址法:线性/二次/随机探测再散列
4、建域法:建立一个公共溢出区存储发生冲突的记录
5、下面是一个我实现的MyHash:解决冲突是采用的第一种方法
package MyHash2; import java.util.Collection; import java.util.Iterator; /** * MyHash类 * @author Administrator * * @param <T> */ public class MyHash<T>implements Collection<T>{ private Entry[] table; private int hashTableSize; private int Capacity=16;//初始大小 private float LoadFactor= 0.75f;//默认装载因子 private int tableThreshold;//最大承载大小 private int modCount=0; /** * 结点类 * @author Administrator * * @param <T> */ private static class Entry<T>{ T value;//数值 int hashvalue;//hash值 Entry<T> next;//指针 public Entry(T value,int hashvalue,Entry<T> next){ this.value=value; this.hashvalue=hashvalue; this.next=next; } } /** * 构造函数 */ public MyHash(){ table=new Entry[Capacity]; hashTableSize=0; tableThreshold =(int)(table.length * LoadFactor); } /** * 添加数据 */ public boolean add(T item){ int hashvalue=item.hashCode();//计算hashvalue int index=hashvalue%table.length;//计算下标 //System.out.println("item.hashCode()="+hashvalue+" table.length="+table.length+" index="+index); Entry<T> entry; entry= table[index]; //不为空,则查找该数据是否已存在;为空则加入 while(entry!=null){ if(entry.value.equals(item)){ System.out.println("该数据已经存在"); return false; } entry=entry.next; } modCount++; entry =new Entry<T>(item,hashvalue,(Entry<T>) table[index]); table[index]=entry; hashTableSize++; //检查hash表是否已超过最大承载量 if(hashTableSize>tableThreshold){ int newTableSize=2 * table.length + 1; rehashing(newTableSize); } // System.out.println("添加数据"+item+"成功"); return true; } /** * 移除数据 */ public boolean remove(Object item){ int index =item.hashCode()%table.length; Entry<T> current; Entry<T> previous=null; current=table[index]; //对应下标的数组位置有数据 while(current!=null){ //找到要删除的数据 if(current.value.equals(item)){ modCount++; //该数据不是链表的第一个数据,则将前一个数据的指针指向下一个数据 if(previous!=null){ previous.next=current.next; }else{//该数据是链表的第一个数据,则将下一个数据挪到当前下标处 table[index]=current.next; } hashTableSize--; System.out.println("删除了数据:"+current.value+" index为"+index); return true; }else{//向下继续找要删除的数据 previous=current; current=current.next; } } return false; } /** * 查找某数据 * @param item * @return */ public boolean find(Object item){ int index=item.hashCode()%table.length;//计算出下标 Entry<T> entry=table[index]; //对数组下标下的链表进行查找 while(entry!=null){ //与对应下标内的数据进行equals比较 if(entry.value.equals(item)){ System.out.println("查找到数据:"+entry.value+" index为"+index); return true; } entry=entry.next; } System.out.println("查找失败,数据不存在"); return false; } /** * 清除所有数据 */ public void clear(){ int len=table.length; //遍历———清空数据 for(int i=0;i < len; i++){ table[i] = null; modCount++; hashTableSize = 0; } } /** * rehash方法 * @param rehashSize */ public void rehashing(int newTableSize){ System.out.println("Hash重构"); Entry[] newTable =new Entry[newTableSize];//新HashTable Entry[] oldTable = table;//原HashTable int index; Entry entry; //循环,将原HashTable内的数据重新计算地址,存入新HashTable for(int i=0;i<table.length;i++){ entry=table[i]; if(entry!=null){ //先将该位置的原数据清除,设为NUll table[i]=null; //向新HashTabele中添加该数据 while(entry!=null){ Entry newEntry=entry.next; index=entry.hashvalue%newTableSize; entry.next = newTable[index]; newTable[index] = entry; entry = newEntry; } } } table=newTable; //重新设置装载量大小 tableThreshold = (int) (table.length * LoadFactor); //将原HashTable清空 oldTable = null; } // /** // * 计算HashCode的方法 // * @return // */ // public int hashcode(Object item){ // int index = item.hashCode()%table.length; // return index; // } @Override public int size() { // TODO Auto-generated method stub return hashTableSize; } @Override public boolean isEmpty() { // TODO Auto-generated method stub return hashTableSize == 0; } @Override public boolean contains(Object o) { // TODO Auto-generated method stub return false; } @Override public Iterator<T> iterator() { // TODO Auto-generated method stub return null; } @Override public Object[] toArray() { // TODO Auto-generated method stub return null; } @Override public <T> T[] toArray(T[] a) { // TODO Auto-generated method stub return null; } @Override public boolean containsAll(Collection<?> c) { // TODO Auto-generated method stub return false; } @Override public boolean addAll(Collection<? extends T> c) { // TODO Auto-generated method stub return false; } @Override public boolean removeAll(Collection<?> c) { // TODO Auto-generated method stub return false; } @Override public boolean retainAll(Collection<?> c) { // TODO Auto-generated method stub return false; } }
Test测试类:
加入150万个数据(打印Size、添加数据所需的时间)—>查找一个特定数据(打印该数据、数据所在数组位置的下标、查找时间)—>删除一个数据(打印Size)—>再次查找该数据(查找失败)—>清空全部数据
Hash重构十七次
添加数据时间为:1906
此时Size为1500000
查找到数据:100000 index为290089
查找数据时间为:0
删除了数据:100000 index为290089
此时Size为1499999
查找失败,数据不存在
查找到数据:100000 index为290089
清除全部数据了,此时Size为0
发现多次执行同一程序,添加数据的时间与之前相比会少。。。
发表评论
-
M个int 排重分析
2012-10-28 00:58 963最近两周学习研究了有关大数据的解决办法,下面就M个int ... -
TCP的三次握手及四次断开
2012-09-19 22:27 757我们知道TCP和UDP是两种 ... -
2012上半年总结
2012-07-03 15:10 918转眼间,2012年已经过去一半了,回想一下自己做了些什么 ... -
黄金矿工游戏总结
2012-07-03 15:16 1343经过近二十天的努力,黄金矿工游戏初见雏型,它是我们对 ... -
画图板总结
2012-02-29 14:05 1316在蓝杰上了几节课后就开始了画图板的开发,从一开始简单的界面到能 ... -
java学习总结
2012-01-08 23:12 7671.八大基本数据类型 byte(字节型8) int(整型 ... -
java学习总结
2012-01-08 23:05 11.八大基本数据类型 byte(字节型8) int(整型 ... -
关键字小结
2011-11-19 10:29 771在蓝杰一个月学习后,我们开班了,1015组,开班后上的第一节 ...
相关推荐
MyHash64_1.4.7.exe是一个计算文件SHA1、MD5值的工具,可以对比两个文件的完整性
查看对比md5,sha1等
一款采用并行计算,充分利用多核CPU性能,快速计算文件哈希值的工具。这款小巧实用的工具,原生单执行文件,采用UPX压缩后体积才几百KB,支持MD5、SHA1、CRC32、SHA256、SHA512等算法;支持哈希值比较、支持多个文件...
一款采用并行计算,充分利用多核CPU性能,快速计算文件哈希值的工具。单文件,整合32位和64位可执行程序。作者drag0n发布的最终版,验证文件的首选。 功能特点: 1、只支持常用的CRC32、MD5、SHA1、SHA256、SHA512...
MyHash是一款由drag0n编写的校验工具,采用并行计算,充分利用多核CPU性能,快速计算文件哈希值的工具。这款小巧实用的工具,原生单执行文件,采用UPX压缩后体积才几百KB,支持MD5、SHA1、CRC32、SHA256、SHA512等...
程序的具体实现如下:本程序是用模板类myhash来实现,包括protected和public属性成员。其中protected成员有*ht(自定义散列表指针)、*empty(bool类型指针,功能是将元素值空、m(散列表容量)、p(除留余数法的除数)...
HashFiles是一款免费的实用程序,用来计算CRC32,MD5文件或多个文件的SHA256和SHA1哈希有用。你不会觉得很难使用的应用程序,它的用户界面是不言自明,需要的用户快来下载吧。 虽然有一个专门的按钮,你可以用...
有想过hash[“A1”] = ... 代码如下:static void Main(string[] args) { MyHash hash = new MyHash(); hash[“A1”] = DateTime.Now; hash[“A2”] = 1; Console.WriteLine(Convert.ToString(hash[“A1”]));
在程序中我们对关键字key应用散列函数H(key)来判断关键字key是否在散列表中,...程序的具体实现如下:本程序是用模板类myhash来实现,包括protected和public属性成员。其中protected成员有*ht(自定义散列表指针)、*e
Hash md5校验工具 是一款小巧好用的哈希计算器 Hash也是一款md5校验工具 Hash支持文件拖放 速度很快 可以计算文件的 MD5 SHA1 CRC32 的值 软件特色: 支持多个文件或文件夹拖放操作; 支持参数启动 参数为一个...
1.哈西表MyHash定义如下: Hashtable MyHash=new Hashtable(); 查看下列语句: MyHash.put(“ten”,new Integer(10)); MyHash.put(“ten”,”Hello”); System.out.print(MyHash.size()); 结果为( )。
多线程hash计算工具。安全可靠,电子数据提取固定必备。支持多线程MD5、SHA256、SHA512等多种hash计算,支持批量计算。
* $servers[$this->myHash($key) % 2] 这样得到其中一台服务器的配置,利用这个配置完成分布式部署 * 在服务器数量不发生变化的情况下,普通hash分布可以很好的运作,当服务器的数量发生变化,问题就来了 * 试想...
$digest = hmac($data, $key, \&myhash); print hmac_hex($data, $key, \&myhash); # OO style use Digest::HMAC; $hmac = Digest::HMAC->new($key, "Digest::MyHash"); $hmac->add($data); $hmac->addfile(*...
- MyHash.exe - reMe.Md # 说明 所有文档均来自官网下载文件,内附MD5校验码(与官网一致)。某些包下载速度极慢(下载共用了5小时),为方便大家而上传的资料 #更新时间 2018-5-7(安装包均是 截止今日,官网发布的...
语法: ECMAScript v3规定了数组直接量的语法,JavaScript 1.2和JScript 3.0实现了它。可以把—个用逗号分隔的表达式列表放在方括号中,创建并初始化—个数组。这些表达式的值将成为数组元素。例如: var a = [1, ...
2、精选实用工具:集成 Everything、MyHash、Notepad2、SwitchOFF 等工具,可实现文 件快速搜索、校验和计算、文本编辑、智能关机等功能; 3、拼音首字母定位:集成 QuickSearch eXtended 部分组件,实现中文...
要求: 页面A进入到页面B,在页面B处理完后返回页面...以 ‘http://localhost/$location/21.1 $location.html#/foo?name=bunny#myhash’ 这个路径为例: 1. 获取当前完整的url路径: $location.absUrl(): // http://loca
myhash.go /** * Created with IntelliJ IDEA. * User: liaojie * Date: 12-9-8 * Time: 下午3:53 * To change this template use File | Settings | File Templates. */ package main import ( crypto/md5 ...