GO語言實現(xiàn) 一 棧和隊列

線性表中当娱,棧和隊列是非常重要的兩種數(shù)據(jù)結(jié)構(gòu)嫁盲,本文將就這兩種數(shù)據(jù)結(jié)構(gòu)進行 golang語言實現(xiàn)

一.棧的實現(xiàn)

我們需要實現(xiàn)如下幾個方法

  1. push()????????向棧中壓入一個元素
  2. pop()??????????從棧頂取出一個元素
  3. isEmpty()????判斷棧是否為空
  4. length()??????獲取棧中元素的數(shù)目
  5. peer()?????????查詢棧頂元素

我們需要注意 peer() 方法并不會將棧頂元素刪除

數(shù)組實現(xiàn)如下:

type stack struct {
    cache []int
}

func (sk *stack) push(n int) {
    sk.cache = append(sk.cache, n)
}

func (sk stack) length() int {
    return len(sk.cache)
}
func (sk *stack) pop() int {
    if sk.length() == 0 {
        return 0
    }
    item := sk.cache[sk.length()-1]
    sk.cache = sk.cache[:len(sk.cache)-1]
    return item
}
func (sk stack) isEmpty() bool {
    return len(sk.cache) == 0
}
func (sk stack) peer() int {
    return sk.cache[sk.length()-1]
}

接下來皇筛,我們將用鏈表實現(xiàn)以下項目,并使用 interface{} 來代替 int實現(xiàn)多種類型的兼容


type stackLink struct {
    Top    *node
    Length int
}

type node struct {
    Val  interface{}
    Prev *node
}

func (sl *stackLink) push(value interface{}) {
    newNode := &node{
        Val:  value,
        Prev: sl.Top}
    sl.Top = newNode
    sl.Length++
}

func (sl *stackLink) pop() interface{} {
    topNodeVal := sl.Top.Val
    sl.Top = sl.Top.Prev
    sl.Length--
    return topNodeVal
}

func (sl stackLink) length() int {
    return sl.Length
}

func (sl stackLink) isEmpty() bool {
    return sl.Length == 0
}

func (sl stackLink) peer() interface{} {
    return sl.Top.Val
}

由于任何的變量都實現(xiàn)了空接口脾拆,所以我們可以通過傳遞空接口來實現(xiàn)在棧中壓入不同元素的目的

二.隊列實現(xiàn)

同樣苦银,我們對于隊列,實現(xiàn)了如下方法:

  1. enqueue()??????????入隊列
  2. dequeue()??????????出隊列
  3. isEmpty()????????????判斷隊列是否為空
  4. getLength()????????獲隊列的長度

鏈表實現(xiàn)方式如下:

type queue struct {
    First *node
    Last  *node
    Len   int
}

type node struct {
    Val  interface{}
    Next *node
    Pre  *node
}
func (qu *queue) enqueue(data interface{}) {
    nNode := &node{
        Val:  data,
        Pre:  qu.First,
        Next: nil}
    if qu.First == nil {
        qu.First = nNode
    } else {
        qu.First.Next = nNode
        qu.First = nNode
    }
    if qu.Last == nil {
        qu.Last = nNode
    }
    qu.Len++
}

func (qu *queue) dequeue() interface{} {
    if qu.Len > 0 {
        nNode := qu.Last.Val
        if qu.Last.Next != nil {
            qu.Last.Next.Pre = nil
        }
        qu.Last = qu.Last.Next
        qu.Len--
        return nNode
    }
    return errors.New("error")
}

func (qu queue) isEmpty() bool {
    return qu.Len <= 0
}

func (qu queue) getLength() int {
    return qu.Len
}

三.棧和隊列的應用

在這一部分铛绰,我們通過棧來實現(xiàn)表達式的計算
例如:我們需要計算 (1+((2+3)*(4*5)))

我們維護兩個棧诈茧,一個是值棧,一個是操作棧捂掰,我們在讀取表達式的時候采取如下的策略:

  1. 如果遇到 '('敢会,我們將忽略它
  2. 如果遇到數(shù)字镊叁,將其壓入值棧
  3. 如果遇到操作符,將其壓入操作棧
  4. 如果遇到 ')'走触,我們從值棧中取出兩個值 n1和 n2晦譬,在操作棧中,我們?nèi)〕鲆粋€操作符 op
  5. 我們進行 n2 op n1的操作(例如 n1 = 3互广,n2 = 9敛腌,op = '/',我們將執(zhí)行 9/3 )
  6. 將所得的結(jié)果壓入值棧
func stackCompute(str string) int {
    var (
        vsk  stackLink
        opsk stackLink
    )
    for _, v := range str {
        if v <= '9' && v >= '0' {
            vsk.push(int(v) - '0')
        } else if v == '+' || v == '-' || v == '*' || v == '/' {
            opsk.push(int(v))
        } else if v == ')' {
            n1 := vsk.pop().(int)
            n2 := vsk.pop().(int)
            op := opsk.pop().(int)
            var ans int
            switch op {
            case '+':
                ans = n2 + n1
            case '-':
                ans = n2 - n1
            case '*':
                ans = n2 * n1
            case '/':
                ans = n2 / n1
            }
            vsk.push(int(ans))
        }
    }
    for !opsk.isEmpty() {
        n1 := vsk.pop().(int)
        n2 := vsk.pop().(int)
        op := opsk.pop().(int)
        var ans int
        switch op {
        case '+':
            ans = n2 + n1
        case '-':
            ans = n2 - n1
        case '*':
            ans = n2 * n1
        case '/':
            ans = n2 / n1
        }
        vsk.push(int(ans))
    }
    char := vsk.pop().(int)
    return int(char)
}

我們?nèi)缦抡{(diào)用

stackCompute("(1+((2+3)\*(4\*5)))")
將會得到結(jié)果 101

參考文獻:
Dynamic Connectivity - 普林斯頓大學 | Coursera

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末惫皱,一起剝皮案震驚了整個濱河市像樊,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌旅敷,老刑警劉巖生棍,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異媳谁,居然都是意外死亡涂滴,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進店門晴音,熙熙樓的掌柜王于貴愁眉苦臉地迎上來柔纵,“玉大人,你說我怎么就攤上這事锤躁「榱希” “怎么了?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵系羞,是天一觀的道長郭计。 經(jīng)常有香客問我,道長椒振,這世上最難降的妖魔是什么昭伸? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮杠人,結(jié)果婚禮上勋乾,老公的妹妹穿的比我還像新娘宋下。我一直安慰自己嗡善,他們只是感情好,可當我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布学歧。 她就那樣靜靜地躺著罩引,像睡著了一般。 火紅的嫁衣襯著肌膚如雪枝笨。 梳的紋絲不亂的頭發(fā)上袁铐,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天揭蜒,我揣著相機與錄音,去河邊找鬼剔桨。 笑死屉更,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的洒缀。 我是一名探鬼主播瑰谜,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼树绩!你這毒婦竟也來了萨脑?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤饺饭,失蹤者是張志新(化名)和其女友劉穎渤早,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體瘫俊,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡鹊杖,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了扛芽。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片仅淑。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖胸哥,靈堂內(nèi)的尸體忽然破棺而出涯竟,到底是詐尸還是另有隱情,我是刑警寧澤空厌,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布庐船,位于F島的核電站,受9級特大地震影響嘲更,放射性物質(zhì)發(fā)生泄漏筐钟。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一赋朦、第九天 我趴在偏房一處隱蔽的房頂上張望篓冲。 院中可真熱鬧,春花似錦宠哄、人聲如沸壹将。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽诽俯。三九已至,卻和暖如春承粤,著一層夾襖步出監(jiān)牢的瞬間暴区,已是汗流浹背闯团。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留仙粱,地道東北人房交。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像伐割,于是被迫代替她去往敵國和親涌萤。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,901評論 2 345