Skip to content

Commit 89c7a94

Browse files
authored
Merge pull request #120 from wesllhey/feature/hash-map
hash map data structure
2 parents 35db52b + e6f2f4e commit 89c7a94

File tree

1 file changed

+141
-0
lines changed

1 file changed

+141
-0
lines changed

data-structures/hash-map/hash_map.go

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
package data-structures
2+
3+
import (
4+
"fmt"
5+
"hash/fnv"
6+
)
7+
8+
var defaultCapacity uint64 = 1 << 10
9+
10+
type node struct {
11+
key interface{}
12+
value interface{}
13+
next *node
14+
}
15+
16+
type hashMap struct {
17+
capacity uint64
18+
size uint64
19+
table []*node
20+
}
21+
22+
func newHashMap() *hashMap {
23+
return &hashMap{
24+
capacity: defaultCapacity,
25+
table: make([]*node, defaultCapacity),
26+
}
27+
}
28+
29+
func (hm *hashMap) get(key interface{}) interface{} {
30+
node := hm.getNodeByHash(hm.hash(key))
31+
32+
if node != nil {
33+
return node.value
34+
}
35+
36+
return nil
37+
}
38+
39+
func (hm *hashMap) put(key interface{}, value interface{}) interface{} {
40+
return hm.putValue(hm.hash(key), key, value)
41+
}
42+
43+
func (hm *hashMap) putValue(hash uint64, key interface{}, value interface{}) interface{} {
44+
if hm.capacity == 0 {
45+
hm.capacity = defaultCapacity
46+
hm.table = make([]*node, defaultCapacity)
47+
}
48+
49+
node := hm.getNodeByHash(hash)
50+
51+
if node == nil {
52+
hm.table[hash] = newNode(key, value)
53+
54+
} else if node.key == key {
55+
hm.table[hash] = newNodeWithNext(key, value, node)
56+
return value
57+
58+
} else {
59+
hm.resize()
60+
return hm.putValue(hash, key, value)
61+
}
62+
63+
hm.size++
64+
65+
return value
66+
67+
}
68+
69+
func (hm *hashMap) contains(key interface{}) bool {
70+
node := hm.getNodeByHash(hm.hash(key))
71+
72+
if node != nil {
73+
return true
74+
}
75+
76+
return false
77+
}
78+
79+
func (hm *hashMap) getNodeByHash(hash uint64) *node {
80+
return hm.table[hash]
81+
}
82+
83+
func (hm *hashMap) resize() {
84+
hm.capacity <<= 1
85+
86+
tempTable := hm.table
87+
88+
hm.table = make([]*node, hm.capacity)
89+
90+
for i := 0; i < len(tempTable); i++ {
91+
node := tempTable[i]
92+
if node == nil {
93+
continue
94+
}
95+
96+
hm.table[hm.hash(node.key)] = node
97+
}
98+
}
99+
100+
func newNode(key interface{}, value interface{}) *node {
101+
return &node{
102+
key: key,
103+
value: value,
104+
}
105+
}
106+
107+
func newNodeWithNext(key interface{}, value interface{}, next *node) *node {
108+
return &node{
109+
key: key,
110+
value: value,
111+
next: next,
112+
}
113+
}
114+
115+
func (hm *hashMap) hash(key interface{}) uint64 {
116+
h := fnv.New64a()
117+
h.Write([]byte(fmt.Sprintf("%v", key)))
118+
119+
hashValue := h.Sum64()
120+
121+
return (hm.capacity - 1) & (hashValue ^ (hashValue >> 16))
122+
}
123+
124+
// func main() {
125+
// hashMap := newHashMap()
126+
127+
// hashMap.put("test-1", 10)
128+
// fmt.Println(hashMap.get("test-1"))
129+
130+
// hashMap.put("test-1", 20)
131+
// hashMap.put("test-2", 30)
132+
// hashMap.put(1, 40)
133+
134+
// fmt.Println(hashMap.get("test-1"))
135+
// fmt.Println(hashMap.get("test-2"))
136+
// fmt.Println(hashMap.get(1))
137+
138+
// fmt.Println(hashMap.contains(2))
139+
// fmt.Println(hashMap.contains(1))
140+
// fmt.Println(hashMap.contains("test-1"))
141+
// }

0 commit comments

Comments
 (0)