java数据结构——哈希表(HashTable)
2024-09-01 08:15:27
哈希表提供了快速的插入操作和查找操作,每一个元素是一个key-value对,其基于数组来实现。
一、Java中HashMap与Hashtable的区别:
HashMap可以接受null键值和值,而Hashtable则不能。
Hashtable是线程安全的,通过synchronized实现线程同步。而HashMap是非线程安全的,但是速度比Hashtable快。
这两个类有许多不同的地方,下面列出了一部分:
a) Hashtable 是 JDK 1 遗留下来的类,而 HashMap 是后来增加的。
b)Hashtable 是同步(synchronized)的,比较慢,但 HashMap 没有同步策略,所以会更快。
c)Hashtable 不允许有个空的 key,但是 HashMap 允许出现一个 null key。
public class Employee {
private String key;
private String 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 Employee(String key, String name) {
this.key = key;
this.name = name;
}
}
员工类
import java.math.BigInteger; public class HashTable {
private Employee[] arr; public HashTable() {
arr = new Employee[1000];
} public HashTable(int Maxsize) {
arr = new Employee[Maxsize];
} // public void Insert(Employee emplo) {//以整型作为索引
// arr[emplo.getKey()] = emplo;
// } public void Insert(Employee emplo) {// 以字符串作为索引
arr[hashTable(emplo.getKey())] = emplo;
} // public Employee Find(int key) {
// return arr[key];
// } public Employee Find(String key) {
return arr[hashTable(key)];
} public int hashTable(String key) {// 转换AscII码存储,但存在码值重复问题
BigInteger hashVal = new BigInteger("0");
BigInteger pow27 = new BigInteger("1"); // int hashVal = 0;
int i = key.length() - 1;
// int pow27 = 1;// 27^0
// for (; i >= 0; i--) {
// int letter = key.charAt(i) - 96;
// hashVal += letter;
// }
// return hashVal;
// }
for (; i >= 0; i--) {
int letter = key.charAt(i) - 96;
BigInteger letterB = new BigInteger(String.valueOf(letter));
hashVal = hashVal.add(letterB.multiply(pow27));// hashVal += letter * pow27; // hashVal += letter * pow27;// 这里会溢出
// pow27*=27
pow27 = pow27.multiply(new BigInteger(String.valueOf(27)));
}
//return hashVal % arr.length;
return hashVal.mod(new BigInteger(String.valueOf(arr.length))).intValue(); }
}
方法类
public class Demo { public static void main(String[] args) {
HashTable ht = new HashTable();
/*ht.Insert(new Employee(1, "Ally"));
ht.Insert(new Employee(2, "Jion"));
ht.Insert(new Employee(3, "Micale"));
ht.Insert(new Employee(4, "Lily")); System.out.println(ht.Find(2).getName());*/ ht.Insert(new Employee("aka", "74")); System.out.println(ht.Find("aka").getName());
} }
演示类
链地址法
public class LinkList {
private Node first;// 火车头,保存头结点的一个指向 public LinkList() {// 初始化
first = null;
} public Node deleteFirst() {// 删除头结点
first = first.next;// 头结点为头结点的下一个
return first;
} public Node find(String key) {// 按值查找,返回null或索引值
Node current = first;// 从头结点开始 while (!key.equals(current.emplo.getKey())) { if (current.next == null) {// 尾结点后继为null
return null;
}
current = current.next;
}
return current;// 找到返回
} public Node delete(String key) {// 删除任意结点
Node current = first;
Node previous = first; while (!key.equals(current.emplo.getKey())) {//找到current返回true !true = false
if (current.next == null) {// 没有找到
return null;
}
previous = current;// 保存邻近的两个结点
current = current.next;
} if (current == first) {// 第一个结点
first = first.next;
} else {// 后面的结点
previous.next = current.next;// 上一个结点的下一个变为当前结点的下一个,当前结点删除
}
return current;// 结点类,返回结点类型
} public void insert(Employee emplo) {// 在头结点之后插入
Node node = new Node(emplo);// 创建新的结点
// 这里深深体会一下精妙之处,first保存着一个指向
node.next = first;// 图示第一步
first = node;// 图示第二步
} }
链表
public class Node {// 包装车厢
/**
* 链结点
*/
public Employee emplo;// 数据域
public Node next;// 指针域,后指针 public Node(Employee emplo) {// 构造函数
this.emplo = emplo;
} }
结点
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(Employee emplo) {// 以字符串作为索引
String key = emplo.getKey();
int hashVal = hashTable(key);
if (arr[hashVal] == null) {
arr[hashVal] = new LinkList();
}
arr[hashVal].insert(emplo);
} public Employee Find(String key) {
int hashVal = hashTable(key);
return arr[hashVal].find(key).emplo;
} public Employee Delete(String key) {
int hashVal = hashTable(key);
return arr[hashVal].delete(key).emplo;
} public int hashTable(String key) {// 转换AscII码存储,但存在码值重复问题
BigInteger hashVal = new BigInteger("0");
BigInteger pow27 = new BigInteger("1"); int i = key.length() - 1;
for (; 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 Demo { public static void main(String[] args) {
HashTable ht = new HashTable();
/*ht.Insert(new Employee(1, "Ally"));
ht.Insert(new Employee(2, "Jion"));
ht.Insert(new Employee(3, "Micale"));
ht.Insert(new Employee(4, "Lily")); System.out.println(ht.Find(2).getName());*/
ht.Insert(new Employee("a", "Jack")); // 开放地址法
ht.Insert(new Employee("ct","Rose"));
ht.Insert(new Employee("b", "Upon")); 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.hashTable("a"));
System.out.println(ht.hashTable("ct"));
} }
测试
参考文献:
https://www.cnblogs.com/aeolian/p/8468632.html
https://www.cnblogs.com/williamjie/p/9099141.html
http://www.luyixian.cn/news_show_10979.aspx
最新文章
- ARCGIS server没有服务、silverlight不能调试、windows server2008安装时跳出“安装程序无法创建新的系统分区也无法定位现有的系统分区”的解决方案
- 烂泥:通过binlog恢复mysql数据库
- mongo数据库的导入导出
- 在线预览文件(pdf)
- 在IT公司,project manager 基本上和秘书,助理什么的差不多
- WinForm - ListView点击空白事件
- Crazy-Links
- R学习笔记 第四篇:函数,分支和循环
- ORM基础之ORM介绍和基础操作
- Tip:JSP标签也称之为Jsp Action(JSP动作)元素
- Codeforces 576E Painting Edges [分治,并查集]
- MOT大连站 | 卓越研发之路:前沿技术落地实践
- CentOS 7安装配置Samba服务器
- Kafka错误“Network is unreachable”和“larger than available brokers”
- Android日志监听工具logcat命令详解(转)
- 【MD5加密】MD5加密编码的坑
- laravel with 渴求式加载指定字段
- 开源免费天气预报接口API以及全国所有地区代码[值得收藏]
- BSGS与二次剩余
- spring: 创建环绕通知