哈希表
2016-07-20 21:13
274 查看
哈希表
1. 什么是哈希表?
哈希表是一种数据结构,它提供了快速的插入操作和查找操作。其基于数据来实现。
2. 哈希化
(1) 直接将关键字作为索引。
(2) 将单词转换为索引。
a) 将字母转换为ASCII码,然后进行相加。
b) 幂的连乘。
c) 压缩可可选值。
3. 压缩后仍然可能出现的问题:
冲突,不能保证每个单词都映射到数组的空白单元。
解决办法:
(1) 开放地址法
(2) 链地址法
代码实现:
开放地址法
1.什么是开发地址法?
当冲突发生时,通过查找数组的一个空位,并将数据填入,而不再用哈希函数得到的数组下标,这个方法叫做开放地址法。
2.数据的插入
3.数据的查找
4.数据的删除
代码实现:
运行结果:
链地址法
1.什么是链地址法:
在哈希表每个单元中设置链表,某个数据项的关键字还是像通常一样映射到哈希表的单元中,而数据项本身插入到单元的链表中。
1. 数据的插入
2. 数据的查找
3. 数据的删除
代码的实现:
/** * 员工信息类 * @author Administrator * */ public class Info { private String key; private String name; public Info(String key, String name) { this.key = key; this.name = name; } public String getKey() { return key; } public void setKey(String key) { this.key = key; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
张三
李四
王五
赵柳
张三
Exception in thread "main" java.lang.NullPointerException
at ch17.HashTable.find(HashTable.java:41)
at ch17.TestHashTable.main(TestHashTable.java:20)
1. 什么是哈希表?
哈希表是一种数据结构,它提供了快速的插入操作和查找操作。其基于数据来实现。
2. 哈希化
(1) 直接将关键字作为索引。
(2) 将单词转换为索引。
a) 将字母转换为ASCII码,然后进行相加。
b) 幂的连乘。
c) 压缩可可选值。
3. 压缩后仍然可能出现的问题:
冲突,不能保证每个单词都映射到数组的空白单元。
解决办法:
(1) 开放地址法
(2) 链地址法
代码实现:
/** * 员工信息类 * @author Administrator * */ public class Info { private String key; //工号 private String name; public Info(String key, String name) { this.key = key; this.name = name; } public String getKey() { return key; } public void setKey(String key) { this.key = key; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
import java.math.BigInteger; public class HashTable { private Info[] arr; /** * 默认的构造方法 */ public HashTable() { arr = new Info[100]; } /** * 指定数组初始化大小 */ public HashTable(int maxSize) { arr = new Info[maxSize]; } /** * 插入数据 */ public void insert(Info info) { arr[hashCode(info.getKey())] = info; } /** * 查找数据 */ public Info find(String key) { return arr[hashCode(key)]; } public int hashCode(String key) { // int hashVal = 0; // for(int i = key.length() - 1; i >= 0; i--) { // int letter = key.charAt(i) - 96; // hashVal += letter; // } // return hashVal; BigInteger hashVal = new BigInteger("0"); BigInteger pow27 = new BigInteger("1"); for(int i = key.length() - 1; i >= 0; i--) { int letter = key.charAt(i) - 96; BigInteger letterB = new BigInteger(String.valueOf(letter)); hashVal = hashVal.add(letterB.multiply(pow27)); pow27 = pow27.multiply(new BigInteger(String.valueOf(27))); } return hashVal.mod(new BigInteger(String.valueOf(arr.length))).intValue(); } }
public class TestHashTable { public static void main(String[] args) { HashTable ht = new HashTable(); ht.insert(new Info("a","张三")); ht.insert(new Info("ct","李四")); ht.insert(new Info("wangwu","王五")); System.out.println(ht.find("a").getName()); System.out.println(ht.find("ct").getName()); } }运行结果:
李四 李四
开放地址法
1.什么是开发地址法?
当冲突发生时,通过查找数组的一个空位,并将数据填入,而不再用哈希函数得到的数组下标,这个方法叫做开放地址法。
2.数据的插入
3.数据的查找
4.数据的删除
代码实现:
/** * 员工信息类 * @author Administrator * */ public class Info { private String key; private String name; public Info(String key, String name) { this.key = key; this.name = name; } public String getKey() { return key; } public void setKey(String key) { this.key = key; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
import java.math.BigInteger; public class HashTable { private Info[] arr; /** * 默认的构造方法 */ public HashTable() { arr = new Info[100]; } /** * 指定数组初始化大小 */ public HashTable(int maxSize) { arr = new Info[maxSize]; } /** * 插入数据 */ public void insert(Info info) { //获得关键字 String key = info.getKey(); //关键字所自定的哈希数 int hashVal = hashCode(key); //如果这个索引已经被占用,而且里面是一个未被删除的数据 while(arr[hashVal] != null && arr[hashVal].getName() != null) { //进行递加 ++hashVal; //循环 hashVal %= arr.length; } arr[hashVal] = info; } /** * 查找数据 */ public Info find(String key) { int hashVal = hashCode(key); while(arr[hashVal] != null) { if(arr[hashVal].getKey().equals(key)) { return arr[hashVal]; } ++hashVal; hashVal %= arr.length; } return null; } /** * 删除数据 * @param key * @return */ public Info delete(String key) { int hashVal = hashCode(key); while(arr[hashVal] != null) { if(arr[hashVal].getKey().equals(key)) { Info tmp = arr[hashVal]; tmp.setName(null); return tmp; } ++hashVal; hashVal %= arr.length; } return null; } public int hashCode(String key) { // int hashVal = 0; // for(int i = key.length() - 1; i >= 0; i--) { // int letter = key.charAt(i) - 96; // hashVal += letter; // } // return hashVal; BigInteger hashVal = new BigInteger("0"); BigInteger pow27 = new BigInteger("1"); for(int i = key.length() - 1; i >= 0; i--) { int letter = key.charAt(i) - 96; BigInteger letterB = new BigInteger(String.valueOf(letter)); hashVal = hashVal.add(letterB.multiply(pow27)); pow27 = pow27.multiply(new BigInteger(String.valueOf(27))); } return hashVal.mod(new BigInteger(String.valueOf(arr.length))).intValue(); } }
public class TestHashTable { public static void main(String[] args) { HashTable ht = new HashTable(); ht.insert(new Info("a","张三")); ht.insert(new Info("ct","李四")); ht.insert(new Info("b","王五")); System.out.println(ht.find("a").getName()); System.out.println(ht.find("ct").getName()); System.out.println(ht.find("b").getName()); ht.delete("b"); System.out.println(ht.find("b").getName()); } }
运行结果:
张三 李四 王五 null
链地址法
1.什么是链地址法:
在哈希表每个单元中设置链表,某个数据项的关键字还是像通常一样映射到哈希表的单元中,而数据项本身插入到单元的链表中。
1. 数据的插入
2. 数据的查找
3. 数据的删除
代码的实现:
/** * 员工信息类 * @author Administrator * */ public class Info { private String key; private String name; public Info(String key, String name) { this.key = key; this.name = name; } public String getKey() { return key; } public void setKey(String key) { this.key = key; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
/* * 链结点,相当于是车厢 */ public class Node { //数据域 public Info info; //指针域 public Node next; public Node(Info info) { this.info = info; } }
/* * 链表,相当于火车 */ public class LinkList { //头结点 private Node first; public LinkList() { first = null; } /** * 插入一个结点,在头结点后进行插入 */ public void insertFirst(Info info) { Node node = new Node(info); node.next = first; first = node; } /** * 删除一个结点,在头结点后进行删除 */ public Node deleteFirst() { Node tmp = first; first = tmp.next; return tmp; } /** * 查找方法 */ public Node find(String key) { Node current = first; while(!key.equals(current.info.getKey())) { if(current.next == null) { return null; } current = current.next; } return current; } /** * 删除方法,根据数据域来进行删除 */ public Node delete(String key) { Node current = first; Node previous = first; while(!key.equals(current.info.getKey())) { if(current.next == null) { return null; } previous = current; current = current.next; } if(current == first) { first = first.next; } else { previous.next = current.next; } return current; } }
import java.math.BigInteger; public class HashTable { private LinkList[] arr; /** * 默认的构造方法 */ public HashTable() { arr = new LinkList[100]; } /** * 指定数组初始化大小 */ public HashTable(int maxSize) { arr = new LinkList[maxSize]; } /** * 插入数据 */ public void insert(Info info) { //获得关键字 String key = info.getKey(); //关键字所自定的哈希数 int hashVal = hashCode(key); if(arr[hashVal] == null) { arr[hashVal] = new LinkList(); } arr[hashVal].insertFirst(info); } /** * 查找数据 */ public Info find(String key) { int hashVal = hashCode(key); return arr[hashVal].find(key).info; } /** * 删除数据 * @param key * @return */ public Info delete(String key) { int hashVal = hashCode(key); return arr[hashVal].delete(key).info; } public int hashCode(String key) { // int hashVal = 0; // for(int i = key.length() - 1; i >= 0; i--) { // int letter = key.charAt(i) - 96; // hashVal += letter; // } // return hashVal; BigInteger hashVal = new BigInteger("0"); BigInteger pow27 = new BigInteger("1"); for(int i = key.length() - 1; i >= 0; i--) { int letter = key.charAt(i) - 96; BigInteger letterB = new BigInteger(String.valueOf(letter)); hashVal = hashVal.add(letterB.multiply(pow27)); pow27 = pow27.multiply(new BigInteger(String.valueOf(27))); } return hashVal.mod(new BigInteger(String.valueOf(arr.length))).intValue(); } }
public static void main(String[] args) { HashTable ht = new HashTable(); ht.insert(new Info("a","张三")); ht.insert(new Info("ct","李四")); ht.insert(new Info("b","王五")); ht.insert(new Info("dt","赵柳")); System.out.println(ht.find("a").getName()); System.out.println(ht.find("ct").getName()); System.out.println(ht.find("b").getName()); System.out.println(ht.find("dt").getName()); // System.out.println(ht.hashCode("a")); // System.out.println(ht.hashCode("ct")); System.out.println(ht.delete("a").getName()); System.out.println(ht.find("a").getName()); } }运行结果:
张三
李四
王五
赵柳
张三
Exception in thread "main" java.lang.NullPointerException
at ch17.HashTable.find(HashTable.java:41)
at ch17.TestHashTable.main(TestHashTable.java:20)
相关文章推荐
- Windows Powershell使用哈希表
- 探索PowerShell (八) 数组、哈希表(附:复制粘贴技巧)
- 轻松学习C#的哈希表
- C#中哈希表(HashTable)用法实例详解(添加/移除/判断/遍历/排序等)
- PHP内核探索:哈希表碰撞攻击原理
- php内核解析:PHP中的哈希表
- java中哈希表及其应用详解
- C#中HashTable的用法
- 哈希函数
- 哈希表及哈希函数研究综述
- Qt中QSet的使用
- 数据结构-散列表(Hash Table)的C++实现模板
- 数据结构——哈希表
- Two Sum,3Sum,3Sum Closest,4Sum
- 哈希表
- Java-Majority Element
- 哈希表及处理冲突的方法
- 常用算法C#实现:字符串包含问题
- 【Redis基本数据结构】字典实现
- 探测法的哈希表的C++实现(最新修改)