参考书籍
算法(第四版)Robert Sedgewick Kevin Wayne
这里使用了无序链表进行存储,链表的实现参考:
无序链表实现
实现文件
文件名:SequentialSearchST.go
package symbolTable
import (
"fmt"
"github.com/spaolacci/murmur3"
"reflect"
)
const INIT_CAPACITY = 4
// 基于拉链法的散列表
type SeparateChainingHashST[Key comparable, Value any] struct {
n int // 键值对总数
m int // 散列表的大小
st []SequentialSearchST[Key, Value]
//compare Comparer[Key]
}
func (s *SeparateChainingHashST[Key, Value]) init() {
if len(s.st) <= INIT_CAPACITY {
st := make([]SequentialSearchST[Key, Value], INIT_CAPACITY)
s.st = st
}
}
// m the initial number of chains
func NewSeparateChainingHashST[Key comparable, Value any](m int) SeparateChainingHashST[Key, Value] {
st := make([]SequentialSearchST[Key, Value], m)
return SeparateChainingHashST[Key, Value]{m: m, st: st}
}
func (s *SeparateChainingHashST[Key, Value]) resize(chains int) (err error) {
temp := NewSeparateChainingHashST[Key, Value](chains)
var val Value
for _, k := range s.Keys() {
if val, err = s.Get(k); err != nil {
return
}
if err = s.Put(k, val); err != nil {
return
}
}
s.m = temp.m
s.n = temp.n
s.st = temp.st
return
}
func (s *SeparateChainingHashST[Key, Value]) hash(key Key) int {
strKey := fmt.Sprintf("%v", key)
hash := int(murmur3.Sum64([]byte(strKey))&0x7fffffffffffffff) % s.m
return hash
}
func (s *SeparateChainingHashST[Key, Value]) Size() int {
return s.n
}
func (s *SeparateChainingHashST[Key, Value]) IsEmpty() bool {
return s.Size() == 0
}
// 判断KEY是否为零值
func (s *SeparateChainingHashST[Key, Value]) isKeyZero(key Key) bool {
var zero Key
return key == zero
}
func (s *SeparateChainingHashST[Key, Value]) isValZero(val Value) bool {
return reflect.ValueOf(val).IsZero()
}
func (s *SeparateChainingHashST[Key, Value]) Get(key Key) (value Value, err error) {
if s.isKeyZero(key) {
return value, nullError
}
i := s.hash(key)
return s.st[i].Get(key)
}
func (s *SeparateChainingHashST[Key, Value]) Put(key Key, val Value) (err error) {
if s.isKeyZero(key) {
return nullError
}
if s.isValZero(val) {
return s.Delete(key)
}
if s.n/s.m >= 10 {
if err = s.resize(s.m * 2); err != nil {
return err
}
}
i := s.hash(key)
//if err = s.st[i].Put(key, val); err != nil {
// return
//}
if !s.st[i].Contains(key) {
s.n++
}
err = s.st[i].Put(key, val)
return
}
func (s *SeparateChainingHashST[Key, Value]) Delete(key Key) (err error) {
if s.isKeyZero(key) {
return nullError
}
i := s.hash(key)
if s.st[i].Contains(key) {
s.n--
}
if err = s.st[i].Delete(key); err != nil {
return
}
if s.m > INIT_CAPACITY && s.n <= s.m*2 {
if err = s.resize(s.m / 2); err != nil {
return err
}
}
return
}
func (s *SeparateChainingHashST[Key, Value]) Keys() []Key {
keys := make([]Key, s.m)
for i := 0; i < s.m; i++ {
keys = append(keys, s.st[i].Keys()...)
}
return keys
}
测试文件
文件名:SequentialSearchST_test.go
package symbolTable
import (
"fmt"
"strconv"
"testing"
)
func TestSeparateChainingHashST(t *testing.T) {
st := NewSeparateChainingHashST[string, int](4)
if st.IsEmpty() != true {
fmt.Println("Expected true, but got false")
}
get, err := st.Get("1")
if err != nil {
return
}
if get != 0 {
t.Errorf("Expected 0, but got %d", get)
}
for i := 0; i < 10; i++ {
st.Put(strconv.Itoa(i+1), i+1)
}
if st.Size() != 10 {
t.Errorf("Expected 10, but got %d", st.Size())
}
get, err = st.Get("1")
if err != nil {
t.Fatal(err)
}
if get != 1 {
t.Errorf("Expected 1, but got %d", get)
}
get, err = st.Get("")
if err == nil {
t.Fatal("Expected error, but got nil")
}
if get != 0 {
t.Errorf("Expected 0, but got %d", get)
}
err = st.Delete("1")
get, err = st.Get("100")
if err != nil {
t.Fatal(err)
}
if get != 0 {
t.Errorf("Expected 0, but got %d", get)
}
if st.IsEmpty() == true {
t.Errorf("Expected false, but got true")
}
err = st.Put("6", 66)
if err != nil {
t.Fatal(err)
}
if v, _ := st.Get("6"); v != 66 {
t.Errorf("Expected 66, but got %d", v)
}
err = st.Delete("6")
if err != nil {
t.Fatal(err)
}
err = st.Delete("0")
if err != nil {
t.Fatal(err)
}
}