Day2 的時候說的猜迷大賽原來是第 34 集的劇情
這天友枝町舉辦了猜迷大賽誰知道小櫻和莓玲都有夠笨。小櫻跟雪兔同隊根本躺分仔,莓玲不知道哪來的自信認為自己會贏,知世為了拍小櫻沒參賽(不然知世參賽的話,這集就不用看了一定是知世贏)。
誰知道比賽比到一半時小櫻又做春夢了,而且還是在懸崖邊,然後...全劇終
到底為什麼小櫻一直做那個夢呢?讓我們繼續看下去...
但在繼續看下去前我們必需要先收服眼前這張「堆疊Golang牌」這樣商人才可以多賣幾張牌從中套利
堆疊有一個概念稱為後進先出,什麼意思呢?比如我們在編輯文件時按復原鍵。
動作A -> 動作B-> 動作C
按一次復原鍵 (取消動作C)
再按一次復原鍵 (取消動作B)
或者是疊衣服,每次一直往上疊,但是都從最上面抽,永遠都不會從下面抽
堆疊跟鏈結串列一樣都是一種資料結構,你可以把堆疊想像成一個型態,但是這個型態必需能實作以下方法
type Element interface{
}
type Stack interface{
Push(Element) // 把元素加入堆疊頂端
Pop() Element // 返回前一次加入的元素(返回頂端的元素)
IsEmpty() bool // 堆疊為空
}
一般情況下,由陣列所實作的堆疊效能較好,因此我們用切片實作(切片底層也是陣列),如果對切片操作不熟悉的魔法使們可以來這裡複習:
#8 切片 Slice | Golang 魔法使
那麼就開始我們的(手刻)旅程吧!
首先我們先創建一個 package,至於要怎麼創建?請複習:#14 套件 Package (2020) & 套件實戰(math, http, sort) | Golang魔法使
我們先建立一些基本的結構體:
./stack/stack.go
package stack
type Stack struct{
list []interface{}
}
func New() *Stack{
s := new(Stack)
s.list = make([]interface{}, 0, 8)
return s
}
func (s *Stack) IsEmpty() bool{
return len(s.list) == 0
}
新增方法
// 取出上一次加入的元素
// 也就是最上層的元素 (切片最尾的元素)
func (s *Stack) Pop() interface{}{
if s.IsEmpty(){
return nil
}
tmp := s.list[len(s.list) - 1]
// 取出時要更新 s.list
// 這麼做的目的是為了讓 slice 的 len 做更新
// 透過 len(s.list) 可以不必額外記憶最頂端的 index
s.list = s.list[:len(s.list)-1]
return tmp
}
// 將新元素堆入頂端 (切片最尾)
func (s *Stack) Push(element interface{}){
// 透過 golang 內建的 append() 函式
// 自動將新元素加入在切片尾
// 除此之外該函式會自動更新切片的 len 值
// 另外若底層陣列不夠時也會自動擴充
s.list = append(s.list, element)
}
// 方便主程式對整個堆疊做遍歷走仿
// 因為有控製讓 len 對齊最尾元素
// 所以可以直接印出或用 for + range 走訪
func (s *Stack) ToSlice() []interface{}{
return s.list
}
./lesson22.go
package main
import(
"practice/stack"
"fmt"
)
func printStack(s *stack.Stack){
list := s.ToSlice()
fmt.Println(list)
}
func main(){
myStack := stack.New()
fmt.Println("push(小櫻)")
myStack.Push("小櫻")
fmt.Println("push(小可)")
myStack.Push("小可")
fmt.Println("push(桃矢)")
myStack.Push("桃矢")
fmt.Println("push(知世)")
myStack.Push("知世")
fmt.Println("push(1)")
myStack.Push(1)
fmt.Println("push(2)")
myStack.Push(2)
fmt.Println("push(3)")
myStack.Push(3)
fmt.Println("push(4)")
myStack.Push(4)
printStack(myStack) // [小櫻 小可 桃矢 知世 1 2 3 4]
fmt.Println("pop()", myStack.Pop())
printStack(myStack) // [小櫻 小可 桃矢 知世 1 2 3]
fmt.Println("pop()", myStack.Pop())
printStack(myStack) // [小櫻 小可 桃矢 知世 1 2]
fmt.Println("pop()", myStack.Pop())
printStack(myStack) // [小櫻 小可 桃矢 知世 1]
fmt.Println("pop()", myStack.Pop())
printStack(myStack) // [小櫻 小可 桃矢 知世]
fmt.Println("push(小郎)")
myStack.Push("小郎")
fmt.Println("push(莓鈴)")
myStack.Push("莓鈴")
printStack(myStack) // [小櫻 小可 桃矢 知世 小郎 莓鈴]
fmt.Println("pop()", myStack.Pop())
printStack(myStack) // [小櫻 小可 桃矢 知世 小郎]
fmt.Println("pop()", myStack.Pop())
printStack(myStack) // [小櫻 小可 桃矢 知世]
fmt.Println("pop()", myStack.Pop())
printStack(myStack) // [小櫻 小可 桃矢]
fmt.Println("pop()", myStack.Pop())
printStack(myStack) // [小櫻 小可]
fmt.Println("pop()", myStack.Pop())
printStack(myStack) // [小櫻]
fmt.Println("pop()", myStack.Pop())
printStack(myStack) // []
fmt.Println("pop()", myStack.Pop())
printStack(myStack) // []
}
Golang 的堆疊實作起來很簡單吧,只要熟悉 Slice 的操作就可以了
因為堆疊操做簡單好用,所以很多硬體是用堆疊來實作儲存裝置
本文圖片來自: