forked from shellfly/algo
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlinear_probing_hash_st.go
139 lines (121 loc) · 2.83 KB
/
linear_probing_hash_st.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
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()
}