散列表的实现通常叫做散列hashing。散列是一种用于以常数平均时间执行插入、删除和查找的技术。但是,那些需要元素间任何排序信息的树操作将不会得到有效的支持。理想的散列表数据结构只不过是一个包含一些项的具有固定大小的数组。通常查找是对项的某个部分(数据域)进行的,这部分叫做关键字。例如,项可以由一个串(作为关键字)和其它一些数据域组成。我们把表的大小记作TableSize,并将其理解为散列数据结构的一部分,而不仅仅是浮动于全局的的某个变量。通常习惯是让表从0到TableSize-1变化。
每个关键字被映射到从0到TableSize-1这个范围中的某个数,并且被放到适当的单元中。这个映射就叫做散列函数,理想情况下它应该计算起来简单,并且应该保证任何两个不同的关键字映射到不同的单元。不过,这是不可能的,因为单元的数目是有限的,而关键字实际上是用不完的。因此,我们寻找一个散列函数,该函数要在单元之间均匀地分配关键字。
这就是散列的基本想法,剩下的问题就是要选择一个函数,决定当两个关键字散列到同一个值得时候(即发生冲突)应该做什么以及如何确定散列表的大小。
import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Random; public class SeparateChainingHashTable<AnyType> { private static final int DEFAULT_TABLE_SIZE = 10;//默认容量 private List<AnyType>[] theLists;//散列表的数组 private int currentSize;//当前数据个数 public SeparateChainingHashTable() { this(DEFAULT_TABLE_SIZE); } public SeparateChainingHashTable(int size) { theLists = new LinkedList[nextPrime(size)]; for (int i = 0; i < theLists.length; i++) { theLists[i] = new LinkedList<AnyType>(); } } /** * 使哈希表变空 */ public void makeEmpty() { for (List<AnyType> list : theLists) { list.clear(); } currentSize = 0; } /** * 哈希表是否包含某元素 * @param x 查询元素 * @return 查询结果 */ public boolean contains(AnyType x) { List<AnyType> whichList = theLists[myhash(x)]; return whichList.contains(x); } /** * 向哈希表中插入某元素,若存在则不操作 * @param x 插入元素 */ public void insert(AnyType x) { List<AnyType> whichList = theLists[myhash(x)]; if (!whichList.contains(x)) { whichList.add(x); if (++currentSize > theLists.length) { rehash(); } } else { } } /** * 向哈希表中删除某元素,若不存在则不操作 * @param x 删除元素 */ public void remove(AnyType x) { List<AnyType> whichList = theLists[myhash(x)]; if (whichList.contains(x)) { whichList.remove(x); currentSize--; } else { } } /** * 哈希算法,有多种实现方法 * @param x 元素 * @return 哈希值 */ private int myhash(AnyType x) { int hashVal = x.hashCode(); hashVal %= theLists.length; if (hashVal < 0) { hashVal += theLists.length; } return hashVal; } /** * 再散列函数,插入空间不够时执行 */ private void rehash() { List<AnyType>[] oldLists = theLists; // 分配一个两倍大小的空表 theLists = new List[nextPrime(2 * theLists.length)]; for(int j=0;j<theLists.length;j++){ theLists[j]=new LinkedList<AnyType>(); } currentSize = 0; for (int i = 0; i < oldLists.length; i++) { for (AnyType item : oldLists[i]) { insert(item); } } } /** * 检查某整数是否为素数 * @param num 检查整数 * @return 检查结果 */ private static boolean isPrime(int num) { if (num == 2 || num == 3) { return true; } if (num == 1 || num % 2 == 0) { return false; } for (int i = 3; i * i <= num; i += 2) { if (num % i == 0) { return false; } } return true; } /** * 返回不小于某个整数的素数 * @param num 整数 * @return 下一个素数(可以相等) */ private static int nextPrime(int num) { if (num == 0 || num == 1 || num == 2) { return 2; } if (num % 2 == 0) { num++; } while (!isPrime(num)) { num += 2; } return num; } /** * 输出散列表 */ public void printTable() { for(int i=0;i<theLists.length;i++){ System.out.println("-----"); Iterator iterator=theLists[i].iterator(); while(iterator.hasNext()){ System.out.print(iterator.next()+" "); } System.out.println(); } } public static void main(String[] args) { Random random = new Random(); SeparateChainingHashTable<Integer> hashTable = new SeparateChainingHashTable<Integer>(); for (int i = 0; i < 30; i++) { hashTable.insert(random.nextInt(30)); } hashTable.printTable(); } }
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/zhang_zp2014/article/details/47980563