共计 4333 个字符,预计需要花费 11 分钟才能阅读完成。
手撸 golang 根本数据结构与算法 数组
缘起
最近浏览 << 我的第一本算法书 >>(【日】石田保辉;宫崎修一)
本系列笔记拟采纳 golang 练习之
数组
数组是一种线性数据结构,
数据按顺序存储在内存的间断空间内。每个数据的内存地址(在内存上的地位)都能够通过数组下标算出,咱们也就能够借此间接拜访指标数据(这叫作“随机拜访”)。拜访数据时应用的是随机拜访(通过下标可计算出内存地址),所以须要的运行工夫仅为恒定的 O(1)。但另一方面,想要向数组中增加新数据时,必须把指标地位前面的数据一个个移开。所以,如果在数组头部增加数据,就须要 O(n) 的工夫。删除操作同理。摘自 << 我的第一本算法书 >>(【日】石田保辉;宫崎修一)
指标
- golang 自带数组和 slice, 但操作方法不够 OO, 本练习拟创立更 OO 的数组接口和办法
设计
- IArray: 定义数组的接口
- IArrayIterator: 定义数组的迭代器
- tCustomArray: 数组的 OO 封装, 实现 IArray 接口
- tArrayIterator: 数组迭代器, 实现 IArrayIterator 接口
单元测试
array_test.go
package data_structure
import (
"learning/gooop/data_structure/array"
"testing"
)
func Test_Array(t *testing.T) {fnAssertTrue := func(b bool, msg string) {
if !b {t.Fatal(msg)
}
}
it := array.NewArray()
t.Log(it.String())
fnAssertTrue(it.String() == "[]", "expecting []")
it.Append(1)
t.Log(it.String())
fnAssertTrue(it.String() == "[1]", "expecting [1]")
e := it.Remove(0)
t.Log(it.String())
fnAssertTrue(e == nil, "expecting e == nil")
fnAssertTrue(it.String() == "[]", "expecting []")
e = it.Insert(0, 1)
t.Log(it.String())
fnAssertTrue(e == nil, "expecting e == nil")
fnAssertTrue(it.String() == "[1]", "expecting [1]")
e = it.Insert(0, 0)
t.Log(it.String())
fnAssertTrue(e == nil, "expecting e == nil")
fnAssertTrue(it.String() == "[0,1]", "expecting [0,1]")
e = it.Insert(2, 2)
t.Log(it.String())
fnAssertTrue(e == nil, "expecting e == nil")
fnAssertTrue(it.String() == "[0,1,2]", "expecting [0,1,2]")
e = it.Set(0, 10)
t.Log(it.String())
fnAssertTrue(e == nil, "expecting e == nil")
fnAssertTrue(it.String() == "[10,1,2]", "expecting [10,1,2]")
e = it.Set(2, 20)
t.Log(it.String())
fnAssertTrue(e == nil, "expecting e == nil")
fnAssertTrue(it.String() == "[10,1,20]", "expecting [10,1,20]")
e,x := it.Get(0)
fnAssertTrue(e == nil, "expecting e == nil")
fnAssertTrue(x == 10, "expecting 10")
e,x = it.Get(2)
fnAssertTrue(e == nil, "expecting e == nil")
fnAssertTrue(x == 20, "expecting 20")
e,_ = it.Get(3)
fnAssertTrue(e != nil, "expecting e != nil")
e,_ = it.Get(-1)
fnAssertTrue(e != nil, "expecting e != nil")
}
测试输入
$ go test -v array_test.go
=== RUN Test_Array
array_test.go:16: []
array_test.go:20: [1]
array_test.go:24: []
array_test.go:29: [1]
array_test.go:34: [0,1]
array_test.go:39: [0,1,2]
array_test.go:44: [10,1,2]
array_test.go:49: [10,1,20]
--- PASS: Test_Array (0.00s)
PASS
ok command-line-arguments 0.002s
IArray.go
定义数组的接口
package array
type IArray interface {Size() int
IsEmpty() bool
IsNotEmpty() bool
Get(i int) (error,interface{})
Set(i int, it interface{}) error
Append(it interface{})
Remove(i int) error
Insert(i int, it interface{}) error
Iterator() IArrayIterator
String() string}
IArrayIterator.go
定义数组的迭代器
package array
type IArrayIterator interface {More() bool
Next() (error,interface{})
}
tCustomArray.go
数组的 OO 封装, 实现 IArray 接口
package array
import (
"errors"
"fmt"
"strings"
)
type tCustomArray struct {items []interface{}
size int
}
var gIndexOutofBoundsError = errors.New("index out of bounds")
func NewArray() IArray {
return &tCustomArray{items: make([]interface{}, 0),
size: 0,
}
}
func (me *tCustomArray) Size() int {return me.size}
func (me *tCustomArray) IsEmpty() bool {return me.size <= 0}
func (me *tCustomArray) IsNotEmpty() bool {return !me.IsEmpty()
}
func (me *tCustomArray) Get(i int) (error,interface{}) {
if i >= me.size || i < 0 {return gIndexOutofBoundsError, nil}
return nil, me.items[i]
}
func (me *tCustomArray) Set(i int, it interface{}) error {
if i >= me.size || i < 0 {return gIndexOutofBoundsError}
me.items[i] = it
return nil
}
func (me *tCustomArray) Append(it interface{}) {me.items = append(me.items, it)
me.size++
}
func (me *tCustomArray) Remove(i int) error {
if i >= me.size || i < 0 {return gIndexOutofBoundsError}
me.items = append(me.items[:i], me.items[i+1:]...)
me.size--
return nil
}
func (me *tCustomArray) Insert(i int, it interface{}) error {
if i > me.size || i < 0 {return gIndexOutofBoundsError}
newItems := make([]interface{}, 0)
newItems = append(newItems, me.items[:i]...)
newItems = append(newItems, it)
newItems = append(newItems, me.items[i:]...)
me.items = newItems
me.size++
return nil
}
func (me *tCustomArray) Iterator() IArrayIterator {return newArrayIterator(me.items)
}
func (me *tCustomArray) String() string {ss := make([]string, me.size)
for i,it := range me.items {ss[i] = fmt.Sprintf("%v", it)
}
return fmt.Sprintf("[%s]", strings.Join(ss, ","))
}
tArrayIterator.go
数组迭代器, 实现 IArrayIterator 接口
package array
type tArrayIterator struct {items []interface{}
count int
pos int
}
func newArrayIterator(items []interface{}) IArrayIterator {size := len(items)
copy := make([]interface{}, size)
for i,it := range items {copy[i] = it
}
return &tArrayIterator{
items: copy,
count: size,
pos: 0,
}
}
func (me *tArrayIterator) More() bool {return me.pos < me.count}
func (me *tArrayIterator) Next() (error,interface{}) {
if me.pos >= me.count {return gIndexOutofBoundsError, nil}
n := me.pos
me.pos++
return nil, me.items[n]
}
(end)
正文完