Files
unisa_strutture_dati_2013_2014/dictionary/ChainingHashTable.java

227 lines
5.7 KiB
Java

package dictionary;
import arraylist.ArrayIndexList;
import arraylist.IndexList;
import exceptions.HashExceptionKey;
import exceptions.InvalidEntryException;
import position.NodePositionList;
import priorityqueue.Entry;
import java.security.InvalidKeyException;
import java.util.Iterator;
/**
* Created with MONSTER.
* User: xgiovio
* Date: 11/05/2014
* Time: 19:28
*/
//Complete implementation by xgiovio
//Collisions resolved via chaining with LogFile
public class ChainingHashTable<K,V> implements Dictionary<K,V> {
IndexList<LogFile<K,V>> table = null;
LogFile<K,V> AVAIBLE = null;
int avaible_slots = 0;
int elements = 0;
int p = 0;
int scale = 0;
int shift = 0;
public ChainingHashTable(int in_p, int in_size){
table = new ArrayIndexList<LogFile<K, V>>(in_size);
AVAIBLE = new LogFile<K, V>();
p = in_p;
java.util.Random rand = new java.util.Random();
scale = rand.nextInt(p-1) + 1;
shift = rand.nextInt(p);
for (int i= 0 ; i< in_size ;i++){
table.add(i,AVAIBLE);
avaible_slots ++;
}
}
public ChainingHashTable(int in_size){
this(109345121,in_size);
}
public ChainingHashTable(){
this(109345121,100);
}
public float load_factor () throws InvalidKeyException{
float ret = (size() / (float)raw_size());
if ( ret >= 0.9 ) {
reformat();
return load_factor();
}
return ret;
}
public int raw_size (){
return table.size();
}
@Override
public int size() {
return elements;
}
@Override
public boolean isEmpty() {
return (size() == 0);
}
protected int hash ( K key){
return (int) ((Math.abs(key.hashCode()*scale + shift) % p) % raw_size());
}
@Override
public Entry<K, V> find(K key) throws InvalidKeyException {
checkKey(key);
int h = hash(key);
if (table.get(h) == AVAIBLE)
return null;
LogFile<K, V> n = table.get(h);
return n.find(key);
}
@Override
public Iterable<Entry<K, V>> findAll(K key) throws InvalidKeyException {
checkKey(key);
int h = hash(key);
if (table.get(h) == AVAIBLE)
return null;
LogFile<K, V> n = table.get(h);
return n.entries();
}
@Override
public Entry<K, V> insert(K key, V value) throws InvalidKeyException {
checkKey(key);
if (load_factor() >= 0.9 )
reformat();
int h = hash(key);
if (table.get(h) == AVAIBLE) {
LogFile<K, V> n = new LogFile<K, V>();
table.set(h,n);
avaible_slots--;
elements++;
return n.insert(key,value);
} else {
LogFile<K, V> n = table.get(h);
elements++;
return n.insert(key,value);
}
}
protected Entry<K, V> insert_refactor(Entry<K,V> in_e) throws InvalidKeyException {
// in_e not checked because used internally
int h = hash(in_e.getKey());
if (table.get(h) == AVAIBLE) {
LogFile<K, V> n = new LogFile<K, V>();
table.set(h,n);
avaible_slots--;
elements++;
return n.insert(in_e);
} else {
LogFile<K, V> n = table.get(h);
elements++;
return n.insert(in_e);
}
}
@Override
public Entry<K, V> remove(Entry<K, V> e) throws InvalidEntryException {
if (e == null)
throw new InvalidEntryException();
int h = hash(e.getKey());
if (table.get(h) == AVAIBLE)
throw new InvalidEntryException();
LogFile<K, V> n = table.get(h);
Entry<K,V> t = n.remove(e);
elements--;
if (n.size() == 0){
table.set(h,AVAIBLE);
avaible_slots++;
}
return t;
}
@Override
public Iterable<Entry<K, V>> entries() {
NodePositionList<Entry<K,V>> ret = new NodePositionList<Entry<K, V>>();
for (int i = 0 ; i< raw_size() ;i++){
if (table.get(i) != AVAIBLE){
Iterator<Entry<K,V>> local_it = table.get(i).entries().iterator();
for (;local_it.hasNext();){
ret.addLast(local_it.next());
}
}
}
return ret;
}
protected void checkKey(K key) throws InvalidKeyException {
if (key == null )
throw new InvalidKeyException("Invalid key");
}
void reformat () throws InvalidKeyException{
Iterable<Entry<K,V>> ite = entries();
int new_size = raw_size() * 2;
IndexList<LogFile<K,V>> table2 = new ArrayIndexList<LogFile<K, V>>(new_size);
avaible_slots = 0;
elements = 0;
java.util.Random rand = new java.util.Random();
scale = rand.nextInt(p-1) + 1; // new hash scaling factor
shift = rand.nextInt(p); //// new hash shifting factor
for (int i= 0 ; i< (new_size) ;i++){
table2.add(i,AVAIBLE);
}
table = table2;
for (Entry<K,V> e : ite){
insert_refactor(e);
}
}
public String toString() {
Iterator<Entry<K,V>> it = entries().iterator();
String to_return = "";
to_return = to_return + "[";
for (;it.hasNext();){
Entry<K,V> t = it.next();
if (it.hasNext()) {
to_return+=(t.toString() + " , ");
} else {
to_return+=(t.toString());
}
}
return to_return+= "]";
}
}