数据结构是哈希表(hashTable)(二)
时间:2022-05-04
本文章向大家介绍数据结构是哈希表(hashTable)(二),主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
public class HashTableDouble {
private DataItem[] hashArray;
private int arraySize;
private int itemNum;
private DataItem nonItem;
public HashTableDouble() {
arraySize = 13;
hashArray = new DataItem[arraySize];
nonItem = new DataItem(-1);
}
public void displayTable() {
System.out.print("Table:");
for (int i = 0; i < arraySize; i++) {
if (hashArray[i] != null) {
System.out.print(hashArray[i].getKey() + " ");
} else {
System.out.print("** ");
}
}
System.out.println("");
}
public int hashFunction1(int key) { // first hash function
return key % arraySize;
}
public int hashFunction2(int key) { // second hash function
return 5 - key % 5;
}
public boolean isFull() {
return (itemNum == arraySize);
}
public boolean isEmpty() {
return (itemNum == 0);
}
public void insert(DataItem item) {
if (isFull()) {
System.out.println("哈希表已满,重新哈希化..");
extendHashTable();
}
int key = item.getKey();
int hashVal = hashFunction1(key);
int stepSize = hashFunction2(key); // 用hashFunction2计算探测步数
while (hashArray[hashVal] != null && hashArray[hashVal].getKey() != -1) {
hashVal += stepSize;
hashVal %= arraySize; // 以指定的步数向后探测
}
hashArray[hashVal] = item;
itemNum++;
}
public void extendHashTable() {
int num = arraySize;
itemNum = 0; // 重新记数,因为下面要把原来的数据转移到新的扩张的数组中
arraySize *= 2; // 数组大小翻倍
DataItem[] oldHashArray = hashArray;
hashArray = new DataItem[arraySize];
for (int i = 0; i < num; i++) {
insert(oldHashArray[i]);
}
}
public DataItem delete(int key) {
if (isEmpty()) {
System.out.println("Hash table is empty!");
return null;
}
int hashVal = hashFunction1(key);
int stepSize = hashFunction2(key);
while (hashArray[hashVal] != null) {
if (hashArray[hashVal].getKey() == key) {
DataItem temp = hashArray[hashVal];
hashArray[hashVal] = nonItem;
itemNum--;
return temp;
}
hashVal += stepSize;
hashVal %= arraySize;
}
return null;
}
public DataItem find(int key) {
int hashVal = hashFunction1(key);
int stepSize = hashFunction2(key);
while (hashArray[hashVal] != null) {
if (hashArray[hashVal].getKey() == key) {
return hashArray[hashVal];
}
hashVal += stepSize;
hashVal %= arraySize;
}
return null;
}
}
class DataItem {
private int iData;
public DataItem(int data) {
iData = data;
}
public int getKey() {
return iData;
}
}
2.链地址法
在开放地址法中,通过再哈希法寻找一个空位解决冲突问题,另一个方法是在哈希表每个单元中设置链表(即链地址法),某个数据项的关键字值还是像通常一样映射到哈希表的单元,而数据项本身插入到这个单元的链表中。其他同样映射到这个位置的数据项只需要加到链表中,不需要在原始的数组中寻找空位。下面看看链地址法的代码:
public class HashTableDouble {
private SortedList[] hashArray; // 数组中存放链表
private int arraySize;
public HashTableDouble(int size) {
arraySize = size;
hashArray = new SortedList[arraySize];
// new出每个空链表初始化数组
for (int i = 0; i < arraySize; i++) {
hashArray[i] = new SortedList();
}
}
public void displayTable() {
for (int i = 0; i < arraySize; i++) {
System.out.print(i + ": ");
hashArray[i].displayList();
}
}
public int hashFunction(int key) {
return key % arraySize;
}
public void insert(LinkNode node) {
int key = node.getKey();
int hashVal = hashFunction(key);
hashArray[hashVal].insert(node); // 直接往链表中添加即可
}
public LinkNode delete(int key) {
int hashVal = hashFunction(key);
LinkNode temp = find(key);
hashArray[hashVal].delete(key);// 从链表中找到要删除的数据项,直接删除
return temp;
}
public LinkNode find(int key) {
int hashVal = hashFunction(key);
LinkNode node = hashArray[hashVal].find(key);
return node;
}
}
这里用的链表是有序链表LinkNode
public class SortedList {
private LinkNode first;
public SortedList() {
first = null;
}
public boolean isEmpty() {
return (first == null);
}
public void insert(LinkNode node) {
int key = node.getKey();
LinkNode previous = null;
LinkNode current = first;
while(current != null && current.getKey() < key) {
previous = current;
current = current.next;
}
if(previous == null) {
first = node;
}
else {
node.next = current;
previous.next = node;
}
}
public void delete(int key) {
LinkNode previous = null;
LinkNode current = first;
if(isEmpty()) {
System.out.println("chain is empty!");
return;
}
while(current != null && current.getKey() != key) {
previous = current;
current = current.next;
}
if(previous == null) {
first = first.next;
}
else {
previous.next = current.next;
}
}
public LinkNode find(int key) {
LinkNode current = first;
while(current != null && current.getKey() <= key) {
if(current.getKey() == key) {
return current;
}
current = current.next;
}
return null;
}
public void displayList() {
System.out.print("List(First->Last):");
LinkNode current = first;
while(current != null) {
current.displayLink();
current = current.next;
}
System.out.println("");
}
}
class LinkNode {
private int iData;
public LinkNode next;
public LinkNode(int data) {
iData = data;
}
public int getKey() {
return iData;
}
public void displayLink() {
System.out.print(iData + " ");
}
}
在没有冲突的情况下,哈希表中执行插入和删除操作可以达到O(1)的时间级。
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- R语言ggmap空间可视化机动车交通事故地图
- 基于matlab的Lorenz系统仿真可视化
- 使用R语言对进行空间数据可视化
- R语言中基于混合数据抽样(MIDAS)回归的HAR-RV模型预测GDP增长
- R语言马尔可夫体制转换模型Markov regime switching
- Python中的ARIMA模型、SARIMA模型和SARIMAX模型对时间序列预测
- python3用ARIMA模型进行时间序列预测
- R语言马尔可夫转换模型研究交通伤亡人数事故预测
- scrapy爬虫框架和selenium的使用:对优惠券推荐网站数据LDA文本挖掘
- 使用R语言进行Metroplis-in-Gibbs采样和MCMC运行分析
- R语言中的马尔科夫机制转换(Markov regime switching)模型
- R语言ARMA-EGARCH模型、集成预测算法对SPX实际波动率进行预测
- nginx快速入门
- R语言中进行期权定价的Heston模型
- 使用R语言随机波动模型SV处理时间序列中的随机波动率