iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 22
0

Day2 的時候說的猜迷大賽原來是第 34 集的劇情

這天友枝町舉辦了猜迷大賽誰知道小櫻和莓玲都有夠笨。小櫻跟雪兔同隊根本躺分仔,莓玲不知道哪來的自信認為自己會贏,知世為了拍小櫻沒參賽(不然知世參賽的話,這集就不用看了一定是知世贏)。

誰知道比賽比到一半時小櫻又做夢了,而且還是在懸崖邊,然後...全劇終

到底為什麼小櫻一直做那個夢呢?讓我們繼續看下去...

但在繼續看下去前我們必需要先收服眼前這張「堆疊Golang牌」這樣商人才可以多賣幾張牌從中套利

什麼是堆疊

堆疊有一個概念稱為後進先出,什麼意思呢?比如我們在編輯文件時按復原鍵。

動作A -> 動作B-> 動作C
按一次復原鍵 (取消動作C)
再按一次復原鍵 (取消動作B)

或者是疊衣服,每次一直往上疊,但是都從最上面抽,永遠都不會從下面抽

堆疊跟鏈結串列一樣都是一種資料結構,你可以把堆疊想像成一個型態,但是這個型態必需能實作以下方法

type Element interface{

}

type Stack interface{
    Push(Element)    // 把元素加入堆疊頂端
    Pop() Element    // 返回前一次加入的元素(返回頂端的元素)
    IsEmpty() bool   // 堆疊為空
}

一般情況下,由陣列所實作的堆疊效能較好,因此我們用切片實作(切片底層也是陣列),如果對切片操作不熟悉的魔法使們可以來這裡複習:
#8 切片 Slice | Golang 魔法使

那麼就開始我們的(手刻)旅程吧!

創建 package

首先我們先創建一個 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 的操作就可以了

因為堆疊操做簡單好用,所以很多硬體是用堆疊來實作儲存裝置

蛤?你說劇情和課程越來越無關了~不要在意這種小事情

本文圖片來自:


上一篇
#21 鏈結串列 Linked-list | Golang魔法使
下一篇
#23 佇列 Queue | Golang魔法使
系列文
Golang魔法使 ─ 30天從零開始學習Go語言 | 比Python還簡單 | 理科生一定學得會 | 文科生不好說30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言