package lastack import ( "github.com/davecgh/go-spew/spew" ) type Node struct { elements []interface{} cur int down *Node } type Stack struct { top *Node cache *Node size int } func (as *Stack) grow() bool { if as.top.cur+1 == cap(as.top.elements) { var grownode *Node if as.cache != nil { grownode = as.cache grownode.cur = -1 as.cache = nil } else { var growsize int if as.size <= 200 { growsize = as.size * 2 } else { growsize = 200 + as.size/4 } grownode = &Node{elements: make([]interface{}, growsize, growsize), cur: -1} } grownode.down = as.top as.top = grownode return true } return false } func (as *Stack) cacheRemove() bool { if as.top.cur == 0 && as.top.down != nil { as.cache = as.top as.top = as.top.down as.cache.down = nil return true } return false } func New() *Stack { s := &Stack{} s.size = 0 s.top = &Node{elements: make([]interface{}, 8, 8), cur: -1} return s } func (as *Stack) Clear() { as.size = 0 as.top = &Node{elements: make([]interface{}, 8, 8), cur: -1} as.cache = nil } func (as *Stack) Empty() bool { return as.size == 0 } func (as *Stack) Size() int { return as.size } func (as *Stack) String() string { content := "" cur := as.top for ; cur != nil; cur = cur.down { for i, _ := range cur.elements { if cur.cur >= i { content += spew.Sprint(cur.elements[cur.cur-i]) + " " } } } if len(content) > 0 { content = content[0 : len(content)-1] } else { content = "" } return content } func (as *Stack) Values() []interface{} { result := make([]interface{}, as.size, as.size) cur := as.top n := 0 for ; cur != nil; cur = cur.down { for i, _ := range cur.elements { if cur.cur >= i { result[n] = cur.elements[cur.cur-i] n++ } } } return result } func (as *Stack) Get(idx int) (interface{}, bool) { if idx < 0 { return nil, false } cur := as.top for cur != nil && idx-cur.cur > 0 { idx = idx - cur.cur - 1 cur = cur.down } if cur == nil { return nil, false } return cur.elements[cur.cur-idx], true } func (as *Stack) Push(v interface{}) { as.grow() as.top.cur++ as.top.elements[as.top.cur] = v as.size++ } func (as *Stack) Pop() (interface{}, bool) { if as.size <= 0 { return nil, false } as.size-- if as.cacheRemove() { return as.cache.elements[as.cache.cur], true } epop := as.top.elements[as.top.cur] as.top.cur-- return epop, true } func (as *Stack) Peek() (interface{}, bool) { if as.size <= 0 { return nil, false } return as.top.elements[as.top.cur], true }