完善: linkedlist

This commit is contained in:
huangsimin
2019-07-19 17:41:28 +08:00
parent 0fad6aae53
commit 76ca4e2a0e
7 changed files with 580 additions and 51 deletions

View File

@@ -0,0 +1,121 @@
package linkedhashmap
import (
"fmt"
linkedlist "github.com/474420502/focus/list/linked_list"
"github.com/davecgh/go-spew/spew"
)
// LinkedHashmap
type LinkedHashmap struct {
list *linkedlist.LinkedList
hmap map[interface{}]interface{}
}
// New
func New() *LinkedHashmap {
lhmap := &LinkedHashmap{list: linkedlist.New(), hmap: make(map[interface{}]interface{})}
return lhmap
}
// PushBack if key exists, push value replace the value is exists. size is unchanging
func (lhmap *LinkedHashmap) PushBack(key interface{}, value interface{}) {
if _, ok := lhmap.hmap[key]; !ok {
lhmap.list.PushBack(key)
}
lhmap.hmap[key] = value
}
// PushFront if key exists, push value replace the value is exists. size is unchanging
func (lhmap *LinkedHashmap) PushFront(key interface{}, value interface{}) {
if _, ok := lhmap.hmap[key]; !ok {
lhmap.list.PushFront(key)
}
lhmap.hmap[key] = value
}
// Insert 如果成功在该位置返回True, 否则返回false
func (lhmap *LinkedHashmap) Insert(idx uint, key interface{}, value interface{}) bool {
if _, ok := lhmap.hmap[key]; !ok {
return true
}
return false
}
// Get
func (lhmap *LinkedHashmap) Get(key interface{}) (interface{}, bool) {
value, ok := lhmap.hmap[key]
return value, ok
}
// Clear
func (lhmap *LinkedHashmap) Clear() {
lhmap.list.Clear()
lhmap.hmap = make(map[interface{}]interface{})
}
// Remove if key not exists reture nil, false.
func (lhmap *LinkedHashmap) Remove(key interface{}) (interface{}, bool) {
if v, ok := lhmap.hmap[key]; ok {
delete(lhmap.hmap, key)
lhmap.list.RemoveIf(func(idx uint, lkey interface{}) linkedlist.RemoveState {
if lkey == key {
return linkedlist.RemoveAndBreak
}
return linkedlist.UnremoveAndContinue
})
return v, true
}
return nil, false
}
// RemoveIndex
func (lhmap *LinkedHashmap) RemoveIndex(idx uint) (interface{}, bool) {
if lhmap.list.Size() <= idx {
panic(fmt.Sprintf("out of list range, size is %d, idx is %d", lhmap.list.Size(), idx))
}
if _, ok := lhmap.hmap[key]; ok {
delete(lhmap.hmap, key)
lhmap.list.RemoveIf(func(idx uint, lkey interface{}) linkedlist.RemoveState {
if lkey == key {
return linkedlist.RemoveAndBreak
}
return linkedlist.UnremoveAndContinue
})
}
}
// Empty returns true if map does not contain any elements
func (lhmap *LinkedHashmap) Empty() bool {
return lhmap.Size() == 0
}
// Size returns number of elements in the map.
func (lhmap *LinkedHashmap) Size() uint {
return lhmap.list.Size()
}
// Keys returns all keys left to right (head to tail)
func (lhmap *LinkedHashmap) Keys() []interface{} {
return lhmap.list.Values()
}
// Values returns all values in-order based on the key.
func (lhmap *LinkedHashmap) Values() []interface{} {
values := make([]interface{}, lhmap.Size())
count := 0
lhmap.list.Traversal(func(key interface{}) bool {
values[count] = lhmap.hmap[key]
count++
return true
})
return values
}
// String returns a string
func (lhmap *LinkedHashmap) String() string {
return spew.Sprint(lhmap.Values())
}

View File

@@ -0,0 +1,98 @@
package linkedhashmap
import (
"reflect"
"testing"
)
func TestPush(t *testing.T) {
lhm := New()
lhm.PushFront(1, "1")
lhm.PushBack("2", 2)
var values []interface{}
values = lhm.Values()
var testType reflect.Type
if testType = reflect.TypeOf(values[0]); testType.String() != "string" {
t.Error(testType)
}
if testType = reflect.TypeOf(values[1]); testType.String() != "int" {
t.Error(testType)
}
// 1 2
lhm.PushFront(4, "4") // 4 1 2
lhm.PushBack("3", 3) // 4 1 2 3
if lhm.String() != "[4 1 2 3]" {
t.Error(lhm.String())
}
}
func TestBase(t *testing.T) {
lhm := New()
for i := 0; i < 10; i++ {
lhm.PushBack(i, i)
}
if lhm.Empty() {
t.Error("why lhm Enpty, check it")
}
if lhm.Size() != 10 {
t.Error("why lhm Size != 10, check it")
}
lhm.Clear()
if !lhm.Empty() {
t.Error("why lhm Clear not Empty, check it")
}
if lhm.Size() != 0 {
t.Error("why lhm Size != 0, check it")
}
}
func TestGet(t *testing.T) {
lhm := New()
for i := 0; i < 10; i++ {
lhm.PushBack(i, i)
}
for i := 0; i < 10; i++ {
lhm.PushBack(i, i)
}
if lhm.Size() != 10 {
t.Error("why lhm Size != 10, check it")
}
for i := 0; i < 10; i++ {
if v, ok := lhm.Get(i); !ok || v != i {
t.Error("ok is ", ok, " get value is ", v)
}
}
}
func TestRemove(t *testing.T) {
lhm := New()
for i := 0; i < 10; i++ {
lhm.PushBack(i, i)
}
var resultStr = "[0 1 2 3 4 5 6 7 8 9]"
for i := 0; i < 10; i++ {
if lhm.String() != resultStr {
t.Error(lhm.String(), resultStr)
}
lhm.Remove(i)
if lhm.Size() != uint(9-i) {
t.Error("why lhm Size != ", uint(9-i), ", check it")
}
resultStr = resultStr[0:1] + resultStr[3:]
}
}