最近閱讀<<個人第一本算法書>>(【日】石田保輝;宮崎修一)
本系列筆記擬採用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)測試