package algs4 // LinearProbingHashST is symbol table type LinearProbingHashST struct { n int // size of key value pairs m int // hash table size keys []HashKey // defined in separate_chaining_hash_st.go vals []interface{} } // NewLinearProbingHashST ... func NewLinearProbingHashST(capacity int) *LinearProbingHashST { initCapacity := 4 if capacity == 0 { capacity = initCapacity } keys := make([]HashKey, capacity) vals := make([]interface{}, capacity) return &LinearProbingHashST{m: capacity, keys: keys, vals: vals} } func (st *LinearProbingHashST) resize(capacity int) { tmpST := NewLinearProbingHashST(capacity) for i := 0; i < st.m; i++ { if st.keys[i] != nil { tmpST.Put(st.keys[i], st.vals[i]) } } st.keys = tmpST.keys st.vals = tmpST.vals st.m = tmpST.m } func (st *LinearProbingHashST) hash(key HashKey) int { return (key.hash() & 0x7fffffff) % st.m } // Put add new key value pair into the st func (st *LinearProbingHashST) Put(key HashKey, val interface{}) { if key == nil { panic("key is nil") } if val == nil { st.Delete(key) return } // // double table size if 50% full if st.n >= st.m/2 { st.resize(2 * st.m) } var i int for i = st.hash(key); st.keys[i] != nil; i = (i + 1) % st.m { if st.keys[i] == key { st.vals[i] = val return } } st.keys[i] = key st.vals[i] = val st.n++ } // Get add new key value pair into the st func (st *LinearProbingHashST) Get(key HashKey) interface{} { if key == nil { panic("key is nil") } for i := st.hash(key); st.keys[i] != nil; i = (i + 1) % st.m { if st.keys[i] == key { return st.vals[i] } } return nil } // GetInt return the val as int( have to do this since GO doesn't have generics) func (st *LinearProbingHashST) GetInt(key HashKey) int { return st.Get(key).(int) } // Delete ... func (st *LinearProbingHashST) Delete(key HashKey) { if key == nil { panic("key is nil") } if !st.Contains(key) { return } i := st.hash(key) for ; key != st.keys[i]; i = (i + 1) % st.m { } st.keys[i] = nil st.vals[i] = nil // rehash all keys in same cluster for j := (i + 1) % st.m; st.keys[i] != nil; j = (j + 1) % st.m { key, val := st.keys[j], st.vals[j] st.keys[i] = nil st.vals[i] = nil st.n-- st.Put(key, val) } st.n-- // halves size of array if it's 12.5% full or less if st.n > 0 && st.n <= st.m/8 { st.resize(st.m / 2) } } // Contains ... func (st *LinearProbingHashST) Contains(key HashKey) bool { return st.Get(key) != nil } // Size ... func (st *LinearProbingHashST) Size() int { return st.n } // IsEmpty add new key value pair into the st func (st LinearProbingHashST) IsEmpty() bool { return st.Size() == 0 } // Keys ... func (st *LinearProbingHashST) Keys() []interface{} { queue := NewQueue() for i := 0; i < st.m; i++ { if st.keys[i] != nil { queue.Enqueue(st.keys[i]) } } return queue.Slice() }