package chapter4;
import edu.princeton.cs.algs4.Queue;
import edu.princeton.cs.algs4.SeparateChainingHashST;
import edu.princeton.cs.algs4.StdIn;
import edu.princeton.cs.algs4.StdOut;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class ChainingHashTable<Key extends Comparable<Key>,Value> {
private int length;
private int N;
private ChainingTable<Key, Value>[] chainingTables;
ChainingHashTable(){
this(997);
}
public ChainingHashTable(int m){
this.length = m;
chainingTables = new ChainingTable[m];
for(int i = 0 ; i < m; i++){
chainingTables[i] = new ChainingTable<>();
}
}
private void resize(int newLength){
ChainingHashTable<Key,Value> temp = new ChainingHashTable(newLength);
for(int i = 0; i < this.length; i++){
for(Key key : this.chainingTables[i].keys()){
temp.put(key, this.chainingTables[i].get(key));
}
}
this.chainingTables = temp.chainingTables;
this.N = temp.N;
this.length = newLength;
}
public Value get(Key key){
if(key == null){
throw new IllegalArgumentException("key is null");
}
return this.chainingTables[hashCode(key)].get(key);
}
public void put(Key key, Value val){
if(key == null){
throw new IllegalArgumentException("key is null");
}
if(this.N > 10*this.length){
resize(2*this.length);
}
if(!this.chainingTables[hashCode(key)].contains(key)){
this.N++;
}
this.chainingTables[hashCode(key)].put(key,val);
}
// return keys in symbol table as an Iterable
public Iterable<Key> keys() {
Queue<Key> queue = new Queue<Key>();
for (int i = 0; i < this.length; i++) {
for (Key key : this.chainingTables[i].keys())
queue.enqueue(key);
}
return queue;
}
private int hashCode(Key key){
// s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
//去掉高位,再平均分布到数组当中
//length最好为素数,防止出现整除,影响分布均匀性
return (key.hashCode() & 0x7fffffff) % this.length;
}
public void delete(Key key){
if(this.chainingTables[hashCode(key)].contains(key)){
this.N--;
}
this.chainingTables[hashCode(key)].delete(key);
if(this.N < 2*this.length && this.length >= 4){
resize(this.length/2);
}
}
public static void main(String[] args) {
SeparateChainingHashST<String, Integer> st = new SeparateChainingHashST<String, Integer>();
for (int i = 0; i < 10 ; i++) {
String key = StdIn.readString();
st.put(key, i);
}
// print keys
for (String s : st.keys())
StdOut.println(s + " " + st.get(s));
}
}
class ChainingTable<Key extends Comparable<Key>,Value>{
private int length;
private Node head;
ChainingTable(){
this.head = null;
this.length = 0;
}
private class Node{
private Node next;
private Key key;
private Value value;
Node(Key key, Value value){
this.key = key;
this.value = value;
this.next = null;
}
public Value getValue() {
return value;
}
}
public Value get(Key key){
Node temp = this.head;
while(temp != null){
if(temp.key.compareTo(key) == 0)
return temp.getValue();
temp = temp.next;
}
return null;
}
public void put(Key key, Value value){
if(this.head == null){
this.head = new Node(key,value);
}else {
Node temp = this.head;
while(temp.next != null){
temp = temp.next;
if(temp.key.compareTo(key) == 0)
temp.value = value;
}
temp.next = new Node(key,value);
this.length++;
}
}
public void delete(Key key){
if(this.head.key.compareTo(key) == 0){
this.head = this.head.next;
this.length--;
}else{
Node temp = this.head;
Node preNode = null;
while(temp != null){
if(temp.key.compareTo(key) == 0 && preNode != null){
preNode.next = temp.next;
this.length--;
}
preNode = temp;
temp = temp.next;
}
}
}
public boolean contains(Key key){
Node temp = this.head;
while(temp != null){
if(temp.key.compareTo(key) == 0)
return true;
temp = temp.next;
}
return false;
}
public List<Key> keys(){
List<Key> keys = new ArrayList<>();
Node temp = this.head;
while(temp != null){
keys.add(temp.key);
temp = temp.next;
}
return keys;
}
}
拉链法时数组加链表实现的散列表,主要时hashcode来保证数据的分布,java给不同类型的变量都实现了hashcode。