完成hashmap
This commit is contained in:
parent
36743be520
commit
4ccb4f4016
|
@ -116,6 +116,52 @@ func (tree *avlTree) GetNode(key interface{}) (*avlNode, bool) {
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (tree *avlTree) PutNode(pnode *avlNode) bool {
|
||||||
|
|
||||||
|
pnode.height = 0
|
||||||
|
pnode.children[0] = nil
|
||||||
|
pnode.children[1] = nil
|
||||||
|
// pnode.parent = nil
|
||||||
|
|
||||||
|
if tree.size == 0 {
|
||||||
|
tree.size++
|
||||||
|
tree.root = pnode
|
||||||
|
pnode.parent = nil
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
for cur, c := tree.root, 0; ; {
|
||||||
|
c = tree.Compare(pnode.key, cur.key)
|
||||||
|
if c == -1 {
|
||||||
|
if cur.children[0] == nil {
|
||||||
|
tree.size++
|
||||||
|
cur.children[0] = pnode
|
||||||
|
cur.children[0].parent = cur
|
||||||
|
if cur.height == 0 {
|
||||||
|
tree.fixPutHeight(cur)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
cur = cur.children[0]
|
||||||
|
} else if c == 1 {
|
||||||
|
if cur.children[1] == nil {
|
||||||
|
tree.size++
|
||||||
|
cur.children[1] = pnode
|
||||||
|
cur.children[1].parent = cur
|
||||||
|
if cur.height == 0 {
|
||||||
|
tree.fixPutHeight(cur)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
cur = cur.children[1]
|
||||||
|
} else {
|
||||||
|
cur.key = pnode.key
|
||||||
|
cur.value = pnode.value
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (tree *avlTree) Put(key, value interface{}) bool {
|
func (tree *avlTree) Put(key, value interface{}) bool {
|
||||||
|
|
||||||
if tree.size == 0 {
|
if tree.size == 0 {
|
||||||
|
|
|
@ -10,7 +10,7 @@ type HashMap struct {
|
||||||
growfactor uint
|
growfactor uint
|
||||||
slimmingfactor uint
|
slimmingfactor uint
|
||||||
|
|
||||||
table []interface{}
|
table []*avlTree
|
||||||
|
|
||||||
GetHash HashCode
|
GetHash HashCode
|
||||||
Compare compare.Compare
|
Compare compare.Compare
|
||||||
|
@ -42,49 +42,74 @@ func New(hcode HashCode, comp compare.Compare) *HashMap {
|
||||||
hm.GetHash = hcode
|
hm.GetHash = hcode
|
||||||
hm.Compare = comp
|
hm.Compare = comp
|
||||||
initcap := uint(8)
|
initcap := uint(8)
|
||||||
hm.table = make([]interface{}, initcap, initcap)
|
hm.table = make([]*avlTree, initcap, initcap)
|
||||||
hm.growsize = initcap - initcap>>2
|
hm.countNextGrow()
|
||||||
return hm
|
return hm
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// func (hm *HashMap) grow() {
|
||||||
|
// if hm.size >= hm.growsize {
|
||||||
|
// newsize := hm.size << 1
|
||||||
|
// newtable := make([]*Bucket, newsize, newsize)
|
||||||
|
// hm.growsize = newsize - newsize>>2
|
||||||
|
|
||||||
|
// for _, bucket := range hm.table {
|
||||||
|
// if bucket != nil {
|
||||||
|
// cur := bucket.head
|
||||||
|
// hash := hm.GetHash(cur.Key)
|
||||||
|
// index := hash % newsize
|
||||||
|
// // var bkt *Bucket
|
||||||
|
// bkt := newtable[index]
|
||||||
|
|
||||||
|
// if bkt == nil {
|
||||||
|
// bkt = &Bucket{size: 1}
|
||||||
|
// newtable[index] = bkt
|
||||||
|
// bkt.head = &bNode{Value: cur.Value, Key: cur.Key}
|
||||||
|
|
||||||
|
// cur = cur.Next
|
||||||
|
// }
|
||||||
|
|
||||||
|
// for ; cur != nil; cur = cur.Next {
|
||||||
|
// bn := &bNode{Value: cur.Value, Key: cur.Key}
|
||||||
|
// bkt.size++
|
||||||
|
// bn.Next = bkt.head
|
||||||
|
// bkt.head = bn
|
||||||
|
// }
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
// hm.table = newtable
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
func (hm *HashMap) countNextGrow() {
|
||||||
|
hm.growsize = uint(len(hm.table)) << 2
|
||||||
|
}
|
||||||
|
|
||||||
func (hm *HashMap) grow() {
|
func (hm *HashMap) grow() {
|
||||||
if hm.size >= hm.growsize {
|
if hm.size >= hm.growsize {
|
||||||
newsize := hm.size << 1
|
newsize := hm.size << 1
|
||||||
newtable := make([]interface{}, newsize, newsize)
|
newtable := make([]*avlTree, newsize, newsize)
|
||||||
hm.growsize = newsize - newsize>>2
|
|
||||||
hm.size = 0
|
|
||||||
|
|
||||||
for _, v := range hm.table {
|
|
||||||
if v != nil {
|
|
||||||
bucket := v.(*Bucket)
|
|
||||||
cur := bucket.head
|
|
||||||
hash := hm.GetHash(cur.Key)
|
|
||||||
index := hash % newsize
|
|
||||||
var bkt *Bucket
|
|
||||||
n := newtable[index]
|
|
||||||
|
|
||||||
if n == nil {
|
|
||||||
bkt = &Bucket{size: 1}
|
|
||||||
newtable[index] = bkt
|
|
||||||
bkt.head = &bNode{Value: cur.Value, Key: cur.Key}
|
|
||||||
hm.size++
|
|
||||||
cur = cur.Next
|
|
||||||
} else {
|
|
||||||
bkt = n.(*Bucket)
|
|
||||||
}
|
|
||||||
|
|
||||||
for ; cur != nil; cur = cur.Next {
|
|
||||||
bn := &bNode{Value: cur.Value, Key: cur.Key}
|
|
||||||
hm.size++
|
|
||||||
bkt.size++
|
|
||||||
bn.Next = bkt.head
|
|
||||||
bkt.head = bn
|
|
||||||
}
|
|
||||||
|
|
||||||
|
for _, cur := range hm.table {
|
||||||
|
if cur != nil {
|
||||||
|
cur.Traversal(func(k, v interface{}) bool {
|
||||||
|
hash := hm.GetHash(k)
|
||||||
|
index := hash % newsize
|
||||||
|
bkt := newtable[index]
|
||||||
|
if bkt == nil {
|
||||||
|
bkt = avlNew(hm.Compare)
|
||||||
|
newtable[index] = bkt
|
||||||
|
}
|
||||||
|
bkt.Put(k, v)
|
||||||
|
return true
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
hm.table = newtable
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hm.table = newtable
|
||||||
|
hm.countNextGrow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,74 +118,58 @@ func (hm *HashMap) Put(key, value interface{}) {
|
||||||
|
|
||||||
tlen := uint(len(hm.table))
|
tlen := uint(len(hm.table))
|
||||||
index := hash % tlen
|
index := hash % tlen
|
||||||
n := hm.table[index]
|
bkt := hm.table[index]
|
||||||
|
|
||||||
// if n == nil {
|
if bkt == nil {
|
||||||
// n = avlNew(hm.Compare)
|
bkt = avlNew(hm.Compare)
|
||||||
// hm.table[index] = n
|
hm.table[index] = bkt
|
||||||
// }
|
}
|
||||||
|
|
||||||
// bucket := n.(*avlTree)
|
if bkt.Put(key, value) {
|
||||||
// if bucket.Put(key, value) {
|
hm.size++
|
||||||
|
hm.grow()
|
||||||
|
}
|
||||||
|
|
||||||
|
// if bkt == nil {
|
||||||
|
// nbucket := &Bucket{size: 1}
|
||||||
|
// hm.table[index] = nbucket
|
||||||
|
// nbucket.head = &bNode{Value: value, Key: key}
|
||||||
// hm.size++
|
// hm.size++
|
||||||
|
|
||||||
// if hm.size >= hm.growsize {
|
// hm.grow()
|
||||||
// newsize := hm.size << 1
|
// return
|
||||||
// newtable := make([]interface{}, newsize, newsize)
|
|
||||||
// hm.growsize = newsize - newsize>>2
|
|
||||||
|
|
||||||
// for _, v := range hm.table {
|
|
||||||
// if v != nil {
|
|
||||||
// cur := v.(*avlTree)
|
|
||||||
// cur.Traversal(func(k, v interface{}) bool {
|
|
||||||
// hash := hm.GetHash(k)
|
|
||||||
// index := hash % newsize
|
|
||||||
// n := newtable[index]
|
|
||||||
// if n == nil {
|
|
||||||
// n = avlNew(hm.Compare)
|
|
||||||
// newtable[index] = n
|
|
||||||
// }
|
|
||||||
// bucket := n.(*avlTree)
|
|
||||||
// bucket.Put(k, v)
|
|
||||||
// return true
|
|
||||||
// })
|
|
||||||
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// hm.table = newtable
|
|
||||||
|
|
||||||
// }
|
|
||||||
// }
|
// }
|
||||||
|
|
||||||
if n == nil {
|
// cur := bkt.head
|
||||||
nbucket := &Bucket{size: 1}
|
|
||||||
hm.table[index] = nbucket
|
|
||||||
nbucket.head = &bNode{Value: value, Key: key}
|
|
||||||
hm.size++
|
|
||||||
|
|
||||||
hm.grow()
|
// for cur.Next != nil {
|
||||||
return
|
// if hm.Compare(key, cur.Key) == 0 {
|
||||||
}
|
// cur.Key = key
|
||||||
|
// cur.Value = value
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
// cur = cur.Next
|
||||||
|
// }
|
||||||
|
|
||||||
bkt := n.(*Bucket)
|
// bn := &bNode{Value: value, Key: key}
|
||||||
cur := bkt.head
|
// hm.size++
|
||||||
|
// bkt.size++
|
||||||
|
|
||||||
for cur.Next != nil {
|
// bn.Next = bkt.head
|
||||||
if hm.Compare(key, cur.Key) == 0 {
|
// bkt.head = bn
|
||||||
cur.Key = key
|
|
||||||
cur.Value = value
|
|
||||||
return
|
|
||||||
}
|
|
||||||
cur = cur.Next
|
|
||||||
}
|
|
||||||
|
|
||||||
bn := &bNode{Value: value, Key: key}
|
// hm.grow()
|
||||||
hm.size++
|
}
|
||||||
bkt.size++
|
|
||||||
|
func (hm *HashMap) Get(key interface{}) (interface{}, bool) {
|
||||||
bn.Next = bkt.head
|
hash := hm.GetHash(key)
|
||||||
bkt.head = bn
|
|
||||||
|
tlen := uint(len(hm.table))
|
||||||
hm.grow()
|
index := hash % tlen
|
||||||
|
bkt := hm.table[index]
|
||||||
|
if bkt != nil {
|
||||||
|
return bkt.Get(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,23 +30,61 @@ func bToMb(b uint64) uint64 {
|
||||||
return b / 1024 / 1024
|
return b / 1024 / 1024
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkCount(b *testing.B) {
|
func BenchmarkPut(b *testing.B) {
|
||||||
hm := New(HashInt, compare.Int)
|
hm := New(HashInt, compare.Int)
|
||||||
b.N = 100000
|
b.N = 100000
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
hm.Put(i, i)
|
hm.Put(i, i)
|
||||||
}
|
}
|
||||||
|
|
||||||
b.Log(len(hm.table), hm.size)
|
//b.Log(len(hm.table), hm.size)
|
||||||
PrintMemUsage()
|
//PrintMemUsage()
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkGoCount(b *testing.B) {
|
func BenchmarkGet(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
hm := New(HashInt, compare.Int)
|
||||||
|
b.N = 100000
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
hm.Put(i, i)
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
hm.Get(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
//b.Log(len(hm.table), hm.size)
|
||||||
|
//PrintMemUsage()
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkGoPut(b *testing.B) {
|
||||||
m := make(map[int]int)
|
m := make(map[int]int)
|
||||||
b.N = 100000
|
b.N = 100000
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
m[i] = i
|
m[i] = i
|
||||||
}
|
}
|
||||||
b.Log(len(m))
|
//b.Log(len(m))
|
||||||
PrintMemUsage()
|
//PrintMemUsage()
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkGoGet(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
m := make(map[int]int)
|
||||||
|
b.N = 100000
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
m[i] = i
|
||||||
|
}
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if _, ok := m[i]; !ok {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if _, ok := m[i]; !ok {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//b.Log(len(m))
|
||||||
|
//PrintMemUsage()
|
||||||
}
|
}
|
||||||
|
|
202
hashmap/table.go
Normal file
202
hashmap/table.go
Normal file
|
@ -0,0 +1,202 @@
|
||||||
|
package hashmap
|
||||||
|
|
||||||
|
type Table struct {
|
||||||
|
// ysizes []int
|
||||||
|
// xsizes [][]int
|
||||||
|
// xyproduct int
|
||||||
|
|
||||||
|
size uint
|
||||||
|
growsize uint
|
||||||
|
|
||||||
|
data [][4][4]*avlTree
|
||||||
|
cap uint
|
||||||
|
}
|
||||||
|
|
||||||
|
func newTable() *Table {
|
||||||
|
table := &Table{}
|
||||||
|
table.data = make([][4][4]*avlTree, 4, 4)
|
||||||
|
table.countCap()
|
||||||
|
return table
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Table) countCap() {
|
||||||
|
t.cap = uint(len(t.data)) << 4 // * (4 * 4)
|
||||||
|
}
|
||||||
|
|
||||||
|
// func (t *Table) countNextGrow() {
|
||||||
|
// t.growsize = uint(len(t.data)) << 6 // +4 * (4 * 4)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func (arr *Table) debugValues() []interface{} {
|
||||||
|
// var result []interface{}
|
||||||
|
// for _, z := range arr.data {
|
||||||
|
// if z != nil {
|
||||||
|
// for _, y := range z {
|
||||||
|
// if y == nil {
|
||||||
|
// for i := 0; i < arr.xsize; i++ {
|
||||||
|
// result = append(result, nil)
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// for _, x := range y {
|
||||||
|
// if x == nil {
|
||||||
|
// result = append(result, struct{}{})
|
||||||
|
// } else {
|
||||||
|
// result = append(result, x)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// for i := 0; i < arr.ysize*arr.xsize; i++ {
|
||||||
|
// result = append(result, nil)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return result
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func (arr *Table) Values() []interface{} {
|
||||||
|
// var result []interface{}
|
||||||
|
// for _, z := range arr.data {
|
||||||
|
// if z != nil {
|
||||||
|
|
||||||
|
// for _, y := range z {
|
||||||
|
// if y == nil {
|
||||||
|
// for i := 0; i < arr.xsize; i++ {
|
||||||
|
// result = append(result, nil)
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// for _, x := range y {
|
||||||
|
// if x == nil {
|
||||||
|
// result = append(result, nil)
|
||||||
|
// } else {
|
||||||
|
// result = append(result, x)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// for i := 0; i < arr.ysize*arr.xsize; i++ {
|
||||||
|
// result = append(result, nil)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return result
|
||||||
|
// }
|
||||||
|
|
||||||
|
func (t *Table) Cap() uint {
|
||||||
|
return t.cap
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Table) Grow(size int) {
|
||||||
|
zsize := len(t.data) + size
|
||||||
|
temp := make([][4][4]*avlTree, zsize, zsize)
|
||||||
|
copy(temp, t.data)
|
||||||
|
t.data = temp
|
||||||
|
t.countCap()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Table) GetWithNilSet(idx int, DoSetValue func([4]*avlTree, int)) *avlTree {
|
||||||
|
zindex := idx / 16
|
||||||
|
nidx := (idx % 16)
|
||||||
|
yindex := nidx / 4
|
||||||
|
xindex := nidx % 4
|
||||||
|
|
||||||
|
ydata := t.data[zindex]
|
||||||
|
xdata := ydata[yindex]
|
||||||
|
|
||||||
|
v := xdata[xindex]
|
||||||
|
if v == nil {
|
||||||
|
DoSetValue(xdata, xindex)
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// func (arr *Table) Get(idx int) (interface{}, bool) {
|
||||||
|
// zindex := idx / arr.xyproduct
|
||||||
|
// nextsize := (idx % arr.xyproduct)
|
||||||
|
// yindex := nextsize / arr.xsize
|
||||||
|
// xindex := nextsize % arr.xsize
|
||||||
|
|
||||||
|
// ydata := arr.data[zindex]
|
||||||
|
// if ydata == nil {
|
||||||
|
// return nil, false
|
||||||
|
// }
|
||||||
|
|
||||||
|
// xdata := ydata[yindex]
|
||||||
|
// if xdata == nil {
|
||||||
|
// return nil, false
|
||||||
|
// }
|
||||||
|
|
||||||
|
// v := xdata[xindex]
|
||||||
|
// return v, v != nil
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func (arr *Table) GetOrSet(idx int, DoSetValue func([]interface{}, int)) (result interface{}, isSet bool) {
|
||||||
|
// zindex := idx / arr.xyproduct
|
||||||
|
// nidx := (idx % arr.xyproduct)
|
||||||
|
// yindex := nidx / arr.xsize
|
||||||
|
// xindex := nidx % arr.xsize
|
||||||
|
|
||||||
|
// ydata := arr.data[zindex]
|
||||||
|
// if ydata == nil {
|
||||||
|
// ydata = make([][]interface{}, arr.ysize, arr.ysize)
|
||||||
|
// arr.data[zindex] = ydata
|
||||||
|
// }
|
||||||
|
|
||||||
|
// xdata := ydata[yindex]
|
||||||
|
// if xdata == nil {
|
||||||
|
// xdata = make([]interface{}, arr.xsize, arr.xsize)
|
||||||
|
// ydata[yindex] = xdata
|
||||||
|
// arr.ysizes[zindex]++
|
||||||
|
// }
|
||||||
|
|
||||||
|
// result = xdata[xindex]
|
||||||
|
// if result == nil {
|
||||||
|
// DoSetValue(xdata, xindex)
|
||||||
|
// result = xdata[xindex]
|
||||||
|
// if result == nil {
|
||||||
|
// panic("DoSetValue Not Set <nil> Value")
|
||||||
|
// }
|
||||||
|
// arr.xsizes[zindex][yindex]++
|
||||||
|
// return result, false
|
||||||
|
// }
|
||||||
|
// return result, true
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func (arr *Table) Del(idx int) (interface{}, bool) {
|
||||||
|
// zindex := idx / arr.xyproduct
|
||||||
|
// nextsize := (idx % arr.xyproduct)
|
||||||
|
// yindex := nextsize / arr.xsize
|
||||||
|
// xindex := nextsize % arr.xsize
|
||||||
|
|
||||||
|
// ydata := arr.data[zindex]
|
||||||
|
// if ydata == nil {
|
||||||
|
// return nil, false
|
||||||
|
// }
|
||||||
|
|
||||||
|
// xdata := ydata[yindex]
|
||||||
|
// if xdata == nil {
|
||||||
|
// return nil, false
|
||||||
|
// }
|
||||||
|
|
||||||
|
// v := xdata[xindex]
|
||||||
|
// xdata[xindex] = nil
|
||||||
|
|
||||||
|
// isnotnil := v != nil
|
||||||
|
|
||||||
|
// if isnotnil {
|
||||||
|
// arr.xsizes[zindex][yindex]--
|
||||||
|
// if arr.xsizes[zindex][yindex] == 0 {
|
||||||
|
// arr.data[zindex][yindex] = nil
|
||||||
|
|
||||||
|
// arr.ysizes[zindex]--
|
||||||
|
// if arr.ysizes[zindex] == 0 {
|
||||||
|
// arr.data[zindex] = nil
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return v, isnotnil
|
||||||
|
// }
|
Loading…
Reference in New Issue
Block a user