# 数据结构学习笔记（五）散列、分离链接法

散列为我们一般性的以一种用于常数时间执行插入，删除和查找表的技术，但是那些需要排序信息的将不会得到有效的支持，因此如findMax，findMin等都是散列操作都是散列所不支持的。

散列的核心就是一个可靠的散列函数。

1.假如输入的关键字是整数：

2.关键字为字符串：

public static int hash(String key,int tableSize){
int hashVal = 0;
for(int i=0;i<key.length();i++){
hashVal += key.charAt(i);
}
return hashVal % tableSize;
}

1.分离链接法：

/**
* Hash table execise to learn
* Separate chaining table implementation of hash tables.
* Note that all "matching" is based on the equals method.
* @author ************
*
*/
public class SeparateChainingHashTableExce <AnyType>{

private static final int DEFAULT_TABLE_SIZE = 101;
private List<AnyType> [] theLists;
private int currentSize;
/**
* Constructor the hash table
*/
public SeparateChainingHashTableExce(){
this(DEFAULT_TABLE_SIZE);
}

/**
* Construct the hash table
* @param size approximate table size
*/
public SeparateChainingHashTableExce(int size){
/**
* The arrayLists
*/
for(int i = 0; i < theLists.length;i++){
}
}

/**
* Insert into the hash table if the item is already
* present ,then do nothing
* @param x the item to insert
*/
public void insert(AnyType x){
List<AnyType> whichList = theLists[myhash(x)];
if(!whichList.contains(x)){

//if the table is full ,then rehash the table
if(++ currentSize > theLists.length){
rehash();
}
}
}

/**
*Remove from the hash table
* @param x the item to remove
*/
public void remove(AnyType x){
List<AnyType> whichList = theLists[myhash(x)];
if(whichList.contains(x)){
whichList.remove(x);
currentSize --;
}
}

/**
* Find an item in the hash table
* @param x the item to search for
*/
public boolean contains(AnyType x ){
List<AnyType> whichList = theLists[myhash(x)];
return whichList.contains(x);
}

/**
* Make the hash table logically empty
*/
public void makeEmpty(){
for (int i =0 ; i < theLists.length; i++){
theLists[i].clear();
}
currentSize = 0;
}

/**
* A hash routine for String objects
* @param key the String to hash
* @param tableSize the size of the hash table
* @return the hash value
*/
public static int hash(String key, int tableSize){
int hashVal = 0;
for (int i =0; i<key.length(); i++){
hashVal = 37 * hashVal + key.charAt(i);
}
hashVal %= tableSize;
if(hashVal < 0){
hashVal += tableSize;
}
return hashVal;
}

private void rehash(){
List<AnyType> [] oldLists = theLists;

//Create new double-sized ,empty table
theLists = new List[nextPrime(2 * theLists.length)];
for(int j = 0; j< theLists.length; j++){
}

//Copy the table
currentSize = 0;
for (List<AnyType> list : oldLists) {
for(AnyType item : list){
insert(item);
}

}
}

/**
* to caculate the hash value to find the number of septareChain
* @param x the element input
* @return the hash value response to the element
*/
private int myhash(AnyType x){
int hashVal = theLists.length;
hashVal %= theLists.length;
if(hashVal < 0){
hashVal += theLists.length;
}
return hashVal;
}

/**
* Internal method to find a prime number at least as large as n
* @param n the starting number(must be positive)
* @return a prime number larger than or equal to n
*/
private static int nextPrime(int n ){
if(n % 2 == 0){
n++;
}
for(;!isPrime(n);n+=2)
;
return n;
}

/**
* Internal method to test if a number is prime
* Not an afficent algorithm
* @param n the number to test
* @return the tesult of the test
*/
private static boolean isPrime(int n ){
if(n == 2 || n == 3){
return true;
}
if(n ==1 || n % 2 == 0){
return false;
}

for (int i = 3; i * i <= n; i+=2){
if(n % i == 0)
return false;
}
return true;
}
}
其中利用了一个重要的性质，就是当装填因子小于0.5时，插入的时候将会极少出现失败的情况，所以我们设定的装填因子一个阈值，但能够达到时，就扩充表，然后再进行重新散列，重新散列到新的扩充的表中。当然这里是比较的当前表的大小和当前使用的大小，表满了之后就重新hash。
	public void insert(AnyType x){
List<AnyType> whichList = theLists[myhash(x)];
if(!whichList.contains(x)){

//if the table is full ,then rehash the table
if(++ currentSize > theLists.length){
rehash();
}
}
}


	private void rehash(){
List<AnyType> [] oldLists = theLists;

//Create new double-sized ,empty table
theLists = new List[nextPrime(2 * theLists.length)];
for(int j = 0; j< theLists.length; j++){
}

//Copy the table
currentSize = 0;
for (List<AnyType> list : oldLists) {
for(AnyType item : list){
insert(item);
}

}
}