链地址法比开放地址法要好。
哈希化的效率:
1,线性探测:成功查找P=(1+1/(1-L))/2;不成功查找为P=(1+1/(1-L)^2)/2;其中P为探测序列,L为装填因子
2,二次探测和再哈希法:成功查找P=-log2(1-L)/L;不成功查找P=1/(1-L)
3,链地址法:成功查找和插入P=1+L/2;不成功查找P=1+L
比如装填因子L=1/2时,线性探测成功查找和不成功查找平均需要1.5次和2.5次;二次探测为2次和2次;而对于链地址法,这是一个线性函数,查找很快。随着装填因子变大,链地址法性能下降的最慢。
import java.util.Random; //链地址法 class Link { int data; Link next; public Link(int data) { this.data = data; } } // 有序链表对成功查找没啥影响,但可以减少查找不到的时间 class SortedLink { private Link first; public SortedLink() { first = null; } public void insert(int key) { Link current = first; Link previous = null; Link link = new Link(key); while (current != null && key > current.data) { previous = current; current = current.next; } if (previous == null)// first为null或一开始key最小 first = link; else previous.next = link; link.next = current; } public boolean delete(int key) { Link current = first; Link previous = null; while (current != null && key >= current.data) { if (current.data == key) { if (previous == null)// 如果删除的为第一个 first = first.next; else previous.next = current.next; return true; } previous = current; current = current.next; } return false; } public Link find(int key) { Link current = first; while (current != null && key >= current.data) { if (key == current.data) return current; current = current.next; } return null; } public void displayLink() { Link current = first; while (current != null) { System.out.print(current.data + "/"); current = current.next; } System.out.print(" "); } } public class HashChain { private SortedLink[] linkArray; private int size; public HashChain(int size) { this.size = size; linkArray = new SortedLink[size]; for (int i = 0; i < size; i++) linkArray[i] = new SortedLink(); } public void insert(int key) { int hashval = hashfunc(key); linkArray[hashval].insert(key); } public void find(int key) { int hashval = hashfunc(key); Link link = linkArray[hashval].find(key); if (link != null) System.out.println(link.data); } public void delete(int key) { int hashval = hashfunc(key); boolean bool = linkArray[hashval].delete(key); System.out.println(bool); } private int hashfunc(int key) { return key % size; } public void display() { for (int i = 0; i < size; i++) linkArray[i].displayLink(); System.out.println(); } public static void main(String[] args) { HashChain hash = new HashChain(23); Random rand = new Random(); int[] array = new int[10]; for (int i = 0; i < 10; i++) array[i] = rand.nextInt(1000); for (int n : array) hash.insert(n); hash.display(); int temp = array[3]; hash.find(temp); hash.delete(temp); hash.delete(temp); hash.display(); hash.find(temp); hash.insert(200); hash.display(); } }我们也可以使用平衡树来代替链表,进一步提高查找的效率。import java.util.Random;import RBTree.RBTree;//使用平衡二叉树(红黑树)代替链表建立哈希表@SuppressWarnings({ "unchecked", "rawtypes" })public class HashTree { private RBTree[] itemArray;//参考红黑树实现 private int maxSize; public HashTree(int size) { maxSize = size; itemArray = new RBTree[size]; for (int i = 0; i < size; i++) itemArray[i] = new RBTree(); } public void insert(int key) { int hashval = hashfunc(key); itemArray[hashval].insert(key); } public boolean find(int key) { int hashval = hashfunc(key); return itemArray[hashval].find(key); } public int hashfunc(int key) { return key % maxSize; } public void display() { for (int i = 0; i < maxSize; i++) { if (itemArray[i].root == null) System.out.print("[] "); else { itemArray[i].display(itemArray[i].root); System.out.print(" "); } } System.out.println(); } public static void main(String[] args) { HashTree hash = new HashTree(31); Random rand = new Random(); int[] array = new int[20]; for (int i = 0; i < 20; i++) array[i] = rand.nextInt(100); for (int a : array) hash.insert(a); hash.display(); System.out.println(hash.find(array[5])); }}