CI badges added, gofmt ran

master
Dusan Kasan 7 years ago
parent 2ba748ddc2
commit 6a67505471

@ -1,5 +1,7 @@
# Hashmap # Hashmap
[![Build Status](https://circleci.com/gh/DusanKasan/hashmap.svg?style=shield&circle-token=:circle-token)](https://circleci.com/gh/DusanKasan/hashmap) [![Coverage Status](https://coveralls.io/repos/github/DusanKasan/hashmap/badge.svg?branch=master)](https://coveralls.io/github/DusanKasan/hashmap?branch=master) [![Go Report Card](https://goreportcard.com/badge/github.com/DusanKasan/hashmap)](https://goreportcard.com/report/github.com/DusanKasan/hashmap)
A [Red-Black Tree](https://en.wikipedia.org/wiki/Red%E2%80%93black_tree) [Hash Map](https://en.wikipedia.org/wiki/Hash_table) implementation in Golang that uses user-supplied hashing algorithms. A [Red-Black Tree](https://en.wikipedia.org/wiki/Red%E2%80%93black_tree) [Hash Map](https://en.wikipedia.org/wiki/Hash_table) implementation in Golang that uses user-supplied hashing algorithms.
## Usage ## Usage

@ -1,10 +1,12 @@
package hashmap package hashmap
type color bool type color bool
const black color = false const black color = false
const red color = true const red color = true
type matchPosition int8 type matchPosition int8
const greater matchPosition = 1 const greater matchPosition = 1
const same matchPosition = 0 const same matchPosition = 0
const lower matchPosition = -1 const lower matchPosition = -1
@ -29,6 +31,7 @@ type rbTree struct {
hashFunc func(interface{}) int64 hashFunc func(interface{}) int64
} }
// Create new hash map with supplied hashing function
func New(hashFunc func(i interface{}) int64) *rbTree { func New(hashFunc func(i interface{}) int64) *rbTree {
return &rbTree{hashFunc: hashFunc} return &rbTree{hashFunc: hashFunc}
} }
@ -50,7 +53,6 @@ func (rb *rbTree) Insert(key, value interface{}) {
//find insertion parent and position where we should place child //find insertion parent and position where we should place child
parent, position := findInsertionParent(rb.root, keyHash) parent, position := findInsertionParent(rb.root, keyHash)
//insert the child node //insert the child node
switch position { switch position {
case greater: case greater:
@ -79,7 +81,7 @@ func (rb *rbTree) Insert(key, value interface{}) {
for { for {
if child.parent == nil { if child.parent == nil {
rb.root = child rb.root = child
break; break
} }
child = child.parent child = child.parent
@ -171,7 +173,7 @@ func (rb *rbTree) Remove(key interface{}) (found bool) {
if len(node.collisions) > 0 { if len(node.collisions) > 0 {
if key == node.key { if key == node.key {
for k, v := range (node.collisions) { for k, v := range node.collisions {
node.key = k node.key = k
node.value = v node.value = v
break break
@ -226,7 +228,7 @@ func (rb *rbTree) Remove(key interface{}) (found bool) {
rb.root = nil rb.root = nil
} }
break; break
} }
replacementNodeChild = replacementNodeChild.parent replacementNodeChild = replacementNodeChild.parent
@ -236,7 +238,7 @@ func (rb *rbTree) Remove(key interface{}) (found bool) {
} }
func isLeaf(node *rbTreeNode) bool { func isLeaf(node *rbTreeNode) bool {
return node.left == nil && node.right == nil && node.color == black; return node.left == nil && node.right == nil && node.color == black
} }
//if node is the new root, finish //if node is the new root, finish
@ -264,24 +266,23 @@ func deleteCase2(node *rbTreeNode) {
deleteCase3(node) deleteCase3(node)
} }
func deleteCase3(node *rbTreeNode) { func deleteCase3(node *rbTreeNode) {
sibling := getSibling(node) sibling := getSibling(node)
if node.parent.color == black && sibling.color == black && sibling.left.color == black && sibling.right.color == black { if node.parent.color == black && sibling.color == black && sibling.left.color == black && sibling.right.color == black {
sibling.color = red; sibling.color = red
deleteCase1(node.parent); deleteCase1(node.parent)
} else { } else {
deleteCase4(node); deleteCase4(node)
} }
} }
func deleteCase4(node *rbTreeNode) { func deleteCase4(node *rbTreeNode) {
sibling := getSibling(node) sibling := getSibling(node)
if node.parent.color == red && sibling.color == black && sibling.left.color == black && sibling.right.color == black { if node.parent.color == red && sibling.color == black && sibling.left.color == black && sibling.right.color == black {
sibling.color = red; sibling.color = red
node.parent.color = black; node.parent.color = black
} else { } else {
deleteCase5(node); deleteCase5(node)
} }
} }
@ -305,15 +306,15 @@ func deleteCase5(node *rbTreeNode) {
func deleteCase6(node *rbTreeNode) { func deleteCase6(node *rbTreeNode) {
sibling := getSibling(node) sibling := getSibling(node)
sibling.color = node.parent.color; sibling.color = node.parent.color
node.parent.color = black; node.parent.color = black
if (node == node.parent.left) { if node == node.parent.left {
sibling.right.color = black; sibling.right.color = black
rotateLeft(node.parent); rotateLeft(node.parent)
} else { } else {
sibling.left.color = black; sibling.left.color = black
rotateRight(node.parent); rotateRight(node.parent)
} }
} }
@ -411,19 +412,20 @@ func findInsertionParent(n *rbTreeNode, keyHash int64) (*rbTreeNode, matchPositi
if keyHash > n.keyHash { if keyHash > n.keyHash {
if isLeaf(n.right) { if isLeaf(n.right) {
return n, greater return n, greater
} else {
return findInsertionParent(n.right, keyHash)
} }
return findInsertionParent(n.right, keyHash)
} else if keyHash < n.keyHash { } else if keyHash < n.keyHash {
if isLeaf(n.left) { if isLeaf(n.left) {
return n, lower return n, lower
} else { }
return findInsertionParent(n.left, keyHash) return findInsertionParent(n.left, keyHash)
} }
} else {
return n, same return n, same
} }
}
func getGrandparent(n *rbTreeNode) (g *rbTreeNode) { func getGrandparent(n *rbTreeNode) (g *rbTreeNode) {
if n.parent != nil && n.parent.parent != nil { if n.parent != nil && n.parent.parent != nil {
@ -439,9 +441,9 @@ func getUncle(n *rbTreeNode) (u *rbTreeNode) {
return return
} else if n.parent == g.left { } else if n.parent == g.left {
return g.right return g.right
} else {
return g.left
} }
return g.left
} }
func getSibling(n *rbTreeNode) (u *rbTreeNode) { func getSibling(n *rbTreeNode) (u *rbTreeNode) {
@ -451,8 +453,7 @@ func getSibling(n *rbTreeNode) (u *rbTreeNode) {
if n.parent.left == n { if n.parent.left == n {
return n.parent.right return n.parent.right
} else {
return n.parent.left
}
} }
return n.parent.left
}

@ -1,9 +1,9 @@
package hashmap_test package hashmap_test
import ( import (
"testing"
"github.com/DusanKasan/hashmap" "github.com/DusanKasan/hashmap"
"math/rand" "math/rand"
"testing"
"time" "time"
) )
@ -28,12 +28,12 @@ func TestHashmap(t *testing.T) {
m := hashmap.New(hashFunc) m := hashmap.New(hashFunc)
for key, value := range (input) { for key, value := range input {
t.Logf("Inserting key: %v", key) t.Logf("Inserting key: %v", key)
m.Insert(key, value) m.Insert(key, value)
} }
for key, value := range (input) { for key, value := range input {
v, found := m.Get(key) v, found := m.Get(key)
if !found { if !found {
t.Errorf("Key not found: %v", key) t.Errorf("Key not found: %v", key)
@ -51,7 +51,7 @@ func TestHashmap(t *testing.T) {
removedKeys := []int64{} removedKeys := []int64{}
for len(keys) > 0 { for len(keys) > 0 {
preservedKeys := []int64{} preservedKeys := []int64{}
for i, k := range(keys) { for i, k := range keys {
if i == 0 { if i == 0 {
t.Logf("Removing key: %v", k) t.Logf("Removing key: %v", k)
@ -68,7 +68,7 @@ func TestHashmap(t *testing.T) {
} }
keys = preservedKeys keys = preservedKeys
for _, k := range(keys) { for _, k := range keys {
v, found := m.Get(k) v, found := m.Get(k)
if !found { if !found {
t.Errorf("Key %v not found!", k) t.Errorf("Key %v not found!", k)
@ -77,7 +77,7 @@ func TestHashmap(t *testing.T) {
} }
} }
for _, k := range(removedKeys) { for _, k := range removedKeys {
_, found := m.Get(k) _, found := m.Get(k)
if found { if found {
t.Errorf("Key %v found when it shouldn't have been!", k) t.Errorf("Key %v found when it shouldn't have been!", k)
@ -89,11 +89,11 @@ func TestHashmap(t *testing.T) {
} }
//generate a map with randomized keys and values //generate a map with randomized keys and values
func generateInputPool(size int) (map[int64]int64) { func generateInputPool(size int) map[int64]int64 {
r := map[int64]int64{} r := map[int64]int64{}
values := rand.Perm(size * 4) values := rand.Perm(size * 4)
for index, key := range (rand.Perm(size * 4)) { for index, key := range rand.Perm(size * 4) {
if index%4 == 0 { if index%4 == 0 {
r[int64(key)] = int64(values[index]) r[int64(key)] = int64(values[index])
} }
@ -105,13 +105,13 @@ func generateInputPool(size int) (map[int64]int64) {
func getShuffledKeys(input map[int64]int64) []int64 { func getShuffledKeys(input map[int64]int64) []int64 {
keys := []int64{} keys := []int64{}
for key, _ := range(input) { for key, _ := range input {
keys = append(keys, key) keys = append(keys, key)
} }
order := rand.Perm(len(keys)) order := rand.Perm(len(keys))
result := []int64{} result := []int64{}
for _, k := range(order) { for _, k := range order {
result = append(result, keys[k]) result = append(result, keys[k])
} }

Loading…
Cancel
Save