棧的ADT 數據 棧的數據對象集合為{a1,a2,a3...an},具有相同數據類型,有唯一前驅後續 操作 InitStack() Stack //初始化操作,創建一個空棧 Clear() //清空棧 IsEmpty() bool //棧是否為空,若棧為空,返回 true,否則 返回 false。 ...
棧的ADT
數據
棧的數據對象集合為{a1,a2,a3...an},具有相同數據類型,有唯一前驅後續
操作
- InitStack() *Stack //初始化操作,創建一個空棧
- Clear() //清空棧
- IsEmpty() bool //棧是否為空,若棧為空,返回 true,否則 返回 false。
- Peek() interface{} //若棧存在且非空,返回棧頂元素。
- Push(data interface{}) //將數據data壓入棧
- Pop() //若棧不為空,出棧
- Length() int //返回棧中元素個數
代碼實現
stack.go
package stack
import (
"sync"
)
type Stack struct {
data []interface{}
length int
capacity int
sync.Mutex
}
// 構建一個空棧
func InitStack() *Stack {
return &Stack{data: make([]interface{}, 8), length: 0, capacity: 8}
}
// 壓棧操作
func (s *Stack) Push(data interface{}) {
s.Lock()
defer s.Unlock()
if s.length+1 >= s.capacity {
s.capacity <<= 1
t := s.data
s.data = make([]interface{}, s.capacity)
copy(s.data, t)
}
s.data[s.length] = data
s.length++
}
// 出棧操作
func (s *Stack) Pop() interface{} {
s.Lock()
defer s.Unlock()
if s.length <= 0 {
panic("int stack pop: index out of range")
}
t := s.data[s.length-1]
s.data = s.data[:s.length-1]
s.length--
return t
}
// 返回棧頂元素
func (s *Stack) Peek() interface{} {
s.Lock()
defer s.Unlock()
if s.length <= 0 {
panic("empty stack")
}
return s.data[s.length-1]
}
// 返回當前棧元素個數
func (s *Stack) Count() int {
s.Lock()
defer s.Unlock()
t := s.length
return t
}
// 清空棧
func (s *Stack) Clear() {
s.Lock()
defer s.Unlock()
s.data = make([]interface{}, 8)
s.length = 0
s.capacity = 8
}
// 棧是否為空
func (s *Stack) IsEmpty() bool {
s.Lock()
defer s.Unlock()
b := s.length == 0
return b
}
stack_test.go
package stack
import (
"testing"
gcv "github.com/smartystreets/goconvey/convey"
)
func TestInitStack(t *testing.T) {
s := InitStack()
gcv.Convey("棧不應該為空", t, func() {
gcv.So(s, gcv.ShouldNotBeNil)
})
}
func TestPush(t *testing.T) {
s := InitStack()
for i := 0; i < 100; i++ {
s.Push(i)
}
gcv.Convey("入棧測試", t, func() {
gcv.Convey("棧大小應該為100", func() {
gcv.So(s.length, gcv.ShouldEqual, 100)
})
gcv.Convey("棧中元素應該為0-99", func() {
gcv.So(func() bool {
for i := 0; i < 100; i++ {
if s.data[i] != i {
return false
}
}
return true
}(), gcv.ShouldEqual, true)
})
})
}
func TestPop(t *testing.T) {
gcv.Convey("出棧測試", t, func() {
gcv.Convey("棧中元素應該為99-0", func() {
gcv.So(func() bool {
s := InitStack()
for i := 0; i < 100; i++ {
s.Push(i)
}
for i := 99; i > -1; i-- {
t := s.Pop().(int)
if t != i {
return false
}
}
return true
}(), gcv.ShouldEqual, true)
})
})
}
func TestPeek(t *testing.T) {
gcv.Convey("棧頂操作", t, func() {
s := InitStack()
s.Push(1)
s.Push(2)
tmp := s.Peek().(int)
gcv.So(tmp, gcv.ShouldEqual, 2)
})
}