hashmap oop in golang

发布时间 2023-05-07 12:13:03作者: wallywl
package main

import (
    "fmt"
)

const HASH_BUCKET_SIZE = 3 //1023

type hash_node struct {
    key  interface{}
    val  interface{}
    next *hash_node
}

type HASH_BUCKET [HASH_BUCKET_SIZE]*hash_node

func hash(key interface{}) int {
    hash := 5381
    switch x := key.(type) {
    case string:
        // Time 33 hash
        for _, k := range x {
            hash += (hash << 5) + int(k)
        }

        return (hash % HASH_BUCKET_SIZE)

    case int:

        hash += (hash << 5) + x

        return (hash % HASH_BUCKET_SIZE)
    default:

        _ = x
        return 0
    }
}

func hash_init() HASH_BUCKET {
    //hash bucket to save node address

    hash_bucket_ptr := new(HASH_BUCKET)

    return *hash_bucket_ptr
}

func key_cmp(a interface{}, b interface{}) bool {
    typ := fmt.Sprintf("%T", a)

    switch x := b.(type) {
    case string:
        if typ == "string" {
            if b == a {
                return true
            }
        }
    case int:
        if typ == "int" {
            if b == a {
                return true
            }
        }
    default:
        _ = x
        return false
    }

    return false
}

func (hashmap *HASH_BUCKET) get(key interface{}) interface{} {
    hash := hash(key)

    for node := hashmap[hash]; node != nil; node = node.next {

        if key_cmp(node.key, key) {
            return node.val
        }
    }

    return nil
}

//insert new node addr in the head of linklist
func (hashmap *HASH_BUCKET) insert(node *hash_node) bool {
    val := hashmap.get(node.key)

    if val != nil {
        return false
    }

    hash := hash(node.key)
    head := hashmap[hash]

    node.next = head
    hashmap[hash] = node

    return true
}

func (hashmap *HASH_BUCKET) remove(item *hash_node) bool {
    hash := hash(item.key)

    cur := hashmap[hash]
    if cur == nil {
        return false
    }

    if key_cmp(cur.key, item.key) {
        hashmap[hash] = cur.next
        return true
    }

    for node := cur.next; node != nil; node = node.next {
        if key_cmp(node.key, item.key) {

            cur.next = node.next

            return true
        }

        cur = node
    }

    return false
}

func (hashmap *HASH_BUCKET) iterate() {
    for i := 0; i < HASH_BUCKET_SIZE; i++ {
        fmt.Printf("i %d ---------->  \n", i)
        for node := hashmap[i]; node != nil; node = node.next {
            fmt.Println("   ", node.key, node.val)
        }
    }
}

func main() {
    hashmap := hash_init()

    for i := 0; i < 5; i++ {
        hashmap.insert(&hash_node{i, i + 1, nil})
        hashmap.insert(&hash_node{fmt.Sprintf("key%d", i), fmt.Sprintf("val%d", i+1), nil})
    }

    hashmap.iterate()

    fmt.Println("---------------after del------------")

    rv := hashmap.insert(&hash_node{"key4", "val1", nil})
    if !rv {
        fmt.Println("insert key4 failed")
    }

    rv = hashmap.insert(&hash_node{"key5", "val1", nil})
    if rv {
        fmt.Println("insert key5 success")
    }

    hashmap.remove(&hash_node{"key4", nil, nil})

    hashmap.remove(&hash_node{1, nil, nil})

    hashmap.iterate()

    fmt.Println(hashmap.get(4))

    fmt.Println(hashmap.get("key0"))
}

output

i 0 ---------->  
    key3 val4
    3 4
    key0 val1
    0 1
i 1 ---------->  
    key4 val5
    4 5
    key1 val2
    1 2
i 2 ---------->  
    key2 val3
    2 3
---------------after del------------
insert key4 failed
insert key5 success
i 0 ---------->  
    key3 val4
    3 4
    key0 val1
    0 1
i 1 ---------->  
    4 5
    key1 val2
i 2 ---------->  
    key5 val1
    key2 val3
    2 3
5
val1