**开放地址法:**当冲突发生时,通过查找数组中的一个空位,并将数据确认,而不是用哈希函数得到的数组下标。
缺点:将别的对象的位置占用了。别的对象存储的时候只能查找位置来存放。
**链地址法:**在哈希表每个单元中设置链表,某个数据项的关键字还是像通常一样映射到哈希表的单元中,而数据项本身插入到单元的链表中。
开放地址法Java代码实现:
创建一个存储对象类
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 HashTable {
private Info[] arr;
/**
* 默认构造方法
*/
public HashTable() {
arr = new Info[100];
}
public HashTable(int maxSize) {
arr = new Info[maxSize];
}
/**
* 插入数据
*
* @param info
*/
public void insert(Info info) {
// 获取关键字
String key = info.getKey();
// 关键字所对应的哈希数
int hashVal = hashCode(key);
// 如果这个索引已经被占用,而且里面是一个未被删除的数据
while (arr[hashVal] != null && arr[hashVal].getName() != null) {
// 进行递加
++hashVal;
// 循环.当hashVal到大数组微端时,此时通过取模回到数组第一个位置。
hashVal %= arr.length;
}
arr[hashVal] = info;
}
/**
* 查找操作
*
* @param key
* @return
*/
public Info find(String key) {
int hashValue = hashCode(key);
while (arr[hashValue] != null) {
if (arr[hashValue].getKey().equals(key)) {
return arr[hashValue];
}
++hashValue;
hashValue %= 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;
}
/**
* 将字符串字母转换为ASCII码,然后跟一个指定的数字的幂相乘,得到的结果进行取模
*
* @param key
* @return
*/
public int hashCode(String key) {
// 使用BigInteger而不用int,避免数组越界问题
BigInteger hashValue = 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));
hashValue = hashValue.add(letterB.multiply(pow27));
pow27.multiply(new BigInteger("27"));// pow27的幂每次加1,该数字的底数为27
}
return hashValue.mod(new BigInteger(String.valueOf(arr.length)))
.intValue();
}
}
注意:这里的删除操作是将原先存储的对象的name设为null,我们也可以通过其他方式来进行标注删除该对象的操作。
链地址法Java代码实现:
创建一个存储对象类同上;
创建一个链节点类
/**
* 链节点类
*
* @author tiger
*
*/
public class Node {
// 数据域(保存节点的数据)
public Info info;
// 指针域(下一个节点的引用)
public Node next;
public Node(Info info) {
this.info = info;
}
}
创建一个链表类
/**
* 链表
*
* @author tiger
*
*/
public class LinkList {
// 头结点
private Node first;
public LinkList() {
first = null;
}
/**
* 插入一个节点,在头结点后进行插入
*
* @param value
*/
public void insertFirst(Info value) {
Node node = new Node(value);
node.next = first;
first = node;
}
/**
* 删除一个节点,在头结点进行删除
*/
public Node deleteFirst() {
Node tmp = first;
first = tmp.next;
return tmp;
}
/**
* 通过节点中的数据查找指定节点
*
* @param value
* @return
*/
public Info find(String key) {
Node current = first;
while (!key.equals(current.info.getKey())) {
if (current.next == null) {
return null;
}
current = current.next;
}
return current.info;
}
/**
* 删除方法,根据数据域进行删除
*
* @param value
* @return
*/
public Info 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.info;
}
}
创建一个哈希表类
public class HashTable {
private LinkList[] arr;
/**
* 默认构造方法
*/
public HashTable() {
arr = new LinkList[100];
}
public HashTable(int maxSize) {
arr = new LinkList[maxSize];
}
/**
* 插入数据
*
* @param info
*/
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);
}
/**
* 查找操作
*
* @param key
* @return
*/
public Info find(String key) {
int hashValue = hashCode(key);
if (arr[hashValue] != null) {
return arr[hashValue].find(key);
}
return null;
}
/**
* 删除数据
*
* @param key
* @return
*/
public Info delete(String key) {
int hashVal = hashCode(key);
if (arr[hashVal] != null) {
return arr[hashVal].delete(key);
}
return null;
}
/**
* 将字符串字母转换为ASCII码,然后跟一个指定的数字的幂相乘,得到的结果进行取模
*
* @param key
* @return
*/
public int hashCode(String key) {
// 使用BigInteger而不用int,避免数组越界问题
BigInteger hashValue = 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));
hashValue = hashValue.add(letterB.multiply(pow27));
pow27.multiply(new BigInteger("27"));// pow27的幂每次加1,该数字的底数为27
}
return hashValue.mod(new BigInteger(String.valueOf(arr.length)))
.intValue();
}
}