您的位置:首页 > 其它

哈希表

2016-07-20 21:13 274 查看
哈希表
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)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  哈希表