最近阅读<<个人第一本算法书>>(【日】石田保辉;宫崎修一)
本系列笔记拟采用golang练习之golang
栈(也叫堆栈)也是一种数据呈线性排列的数据结构, 不过在这种结构中, 咱们只能访问最新添加的数据。 栈就像是一摞书, 拿到新书时咱们会把它放在书堆的最上面, 取书时也只能从最上面的新书开始取。 像栈这种最后添加的数据最早被取出, 即“后进先出”的结构, 咱们称为Last In First Out,简称LIFO。 摘自 <<个人第一本算法书>>(【日】石田保辉;宫崎修一)
stack_test.go算法
package data_structure import ( st "learning/gooop/data_structure/stack" "testing" ) func Test_Stack(t *testing.T) { fnAssertTrue := func(b bool, msg string) { if !b { panic(msg) } } stack := st.NewArrayStack(2) state := stack.String() t.Log(state) fnAssertTrue(state == "c=2,t=-1,v=0,items:", "state error") stack.Push(0) state = stack.String() t.Log(state) fnAssertTrue(state == "c=2,t=0,v=1,items:0", "state error") stack.Push(1) state = stack.String() t.Log(state) fnAssertTrue(state == "c=2,t=1,v=2,items:0,1", "state error") stack.Push(2) state = stack.String() t.Log(state) fnAssertTrue(state == "c=4,t=2,v=3,items:0,1,2", "state error") e,v := stack.Peek() fnAssertTrue(e == nil, "expecting e == nil") fnAssertTrue(v == 2, "expecting value 2") e,v = stack.Pop() state = stack.String() t.Log(state) fnAssertTrue(e == nil, "expecting e == nil") fnAssertTrue(v == 2, "expecting value 2") fnAssertTrue(state == "c=4,t=1,v=4,items:0,1", "state error") e,v = stack.Pop() state = stack.String() t.Log(state) fnAssertTrue(e == nil, "expecting e == nil") fnAssertTrue(v == 1, "expecting value 1") fnAssertTrue(state == "c=4,t=0,v=5,items:0", "state error") e,v = stack.Pop() state = stack.String() t.Log(state) fnAssertTrue(e == nil, "expecting e == nil") fnAssertTrue(v == 0, "expecting value 0") fnAssertTrue(state == "c=4,t=-1,v=6,items:", "state error") e,v = stack.Pop() fnAssertTrue(e != nil, "expecting e != nil") iter := stack.Iterator() fnAssertTrue(iter.More() == false, "expecting More() == false") e,v = iter.Next() fnAssertTrue(e != nil, "expecting e != nil") stack.Push(0) state = stack.String() t.Log(state) fnAssertTrue(state == "c=4,t=0,v=7,items:0", "state error") fnAssertTrue(iter.More() == false, "expecting More() == false") e,v = iter.Next() fnAssertTrue(e != nil, "expecting e != nil") stack.Push(1) state = stack.String() t.Log(state) fnAssertTrue(state == "c=4,t=1,v=8,items:0,1", "state error") iter = stack.Iterator() fnAssertTrue(iter.More() == true, "expecting More() == true") e,v = iter.Next() fnAssertTrue(e == nil && v == 0, "expecting v == 0") e,v = iter.Next() fnAssertTrue(e == nil && v == 1, "expecting v == 1") }
$ go test -v stack_test.go === RUN Test_Stack stack_test.go:17: c=2,t=-1,v=0,items: stack_test.go:22: c=2,t=0,v=1,items:0 stack_test.go:27: c=2,t=1,v=2,items:0,1 stack_test.go:32: c=4,t=2,v=3,items:0,1,2 stack_test.go:41: c=4,t=1,v=4,items:0,1 stack_test.go:48: c=4,t=0,v=5,items:0 stack_test.go:55: c=4,t=-1,v=6,items: stack_test.go:70: c=4,t=0,v=7,items:0 stack_test.go:78: c=4,t=1,v=8,items:0,1 --- PASS: Test_Stack (0.00s) PASS ok command-line-arguments 0.003s
堆栈的接口数组
package stack type IStack interface { Size() int IsEmpty() bool IsNotEmpty() bool Push(value interface{}) Pop() (error, interface{}) Peek() (error, interface{}) Iterator() IStackIterator String() string }
堆栈迭代器的接口数据结构
package stack type IStackIterator interface { More() bool Next() (error,interface{}) }
基于自扩容数组的堆栈, 实现IStack接口oop
package stack import ( "errors" "fmt" "strings" ) type tArrayStack struct { items []interface{} capacity int top int version int64 } var gEmptyStackError = errors.New("empty stack") func NewArrayStack(capacity int) IStack { if capacity < 0 { capacity = 0 } return &tArrayStack{ items: make([]interface{}, capacity), capacity: capacity, top: -1, } } func (me *tArrayStack) Size() int { return me.top + 1 } func (me *tArrayStack) IsEmpty() bool { return me.Size() <= 0 } func (me *tArrayStack) IsNotEmpty() bool { return !me.IsEmpty() } func (me *tArrayStack) Push(value interface{}) { me.ensureCapacity(me.Size() + 1) me.top++ me.items[me.top] = value me.version++ } func (me *tArrayStack) ensureCapacity(size int) { if me.capacity >= size { return } for ;me.capacity<size; { me.capacity = maxInt(me.capacity*2, me.capacity+1) } newItems := make([]interface{}, me.capacity) copy(newItems, me.items) me.items = newItems } func maxInt(x, y int) int { if x >= y { return x } return y } func (me *tArrayStack) Pop() (error, interface{}) { if me.IsEmpty() { return gEmptyStackError, nil } i := me.top me.top-- me.version++ return nil, me.items[i] } func (me *tArrayStack) Peek() (error, interface{}) { if me.IsEmpty() { return gEmptyStackError, nil } return nil, me.items[me.top] } func (me *tArrayStack) Iterator() IStackIterator { return newStackIterator(me) } func (me *tArrayStack) String() string { itemStrings := make([]string, me.Size()) for i:=0;i<me.Size();i++ { itemStrings[i] = fmt.Sprintf("%v", me.items[i]) } return fmt.Sprintf("c=%v,t=%v,v=%v,items:%s", me.capacity, me.top, me.version, strings.Join(itemStrings, ",")) }
免拷贝的堆栈迭代器, 实现IStackIterator接口单元测试
package stack import "errors" type tStackIterator struct { stack *tArrayStack pos int version int64 } var gNullStackError = errors.New("stack is null") var gNoMoreElementError = errors.New("no more element") var gConcurrentModificationError = errors.New("concurrent modification error") func newStackIterator(stack *tArrayStack) IStackIterator { return &tStackIterator{ stack: stack, pos: -1, version: stack.version, } } func (me *tStackIterator) More() bool { if me.stack == nil { return false } if me.version != me.stack.version { return false } return me.pos < me.stack.top } func (me *tStackIterator) Next() (error, interface{}) { if me.stack == nil { return gNullStackError, nil } if me.version != me.stack.version { return gConcurrentModificationError, nil } if me.pos >= me.stack.top { return gNoMoreElementError, nil } me.pos++ return nil, me.stack.items[me.pos] }
(end)测试