棧的用法

1. 棧的定義

后進(jìn)先出的數(shù)據(jù)格式——LIFO

2. 用法

類代碼如下

class Stack:
    def __init__(self):
        self.items = []
    def push(self, item):
        self.items.append(item)

    def pop(self):
        return self.items.pop()

    def peek(self):
        return self.items[len(self.items)-1]

    def size(self):
        return len(self.items)

    def is_empty(self):
        return self.items == []

比較簡(jiǎn)單就不交代了,就是增刪查的一些內(nèi)容

3 經(jīng)典例子

  1. 字符消消樂(lè) Leetcode-1
    代碼:
    def removeDuplicates(self, s: str) -> str:
        stack = []
        s = list(s)
        for i in s:
            if not stack:
                stack.append(i)
            elif i == stack[-1]:
                stack.pop()
            else:
                stack.append(i)
        # 字符串化
        res = ''.join(stack)
        return res
  1. 引號(hào)消除 Leetcode-20
# 棧的類
class Stack:
    def __init__(self):
        self.items = []

    def push(self, item):
        self.items.append(item)

    def pop(self):
        return self.items.pop()

    def peek(self):
        return self.items[len(self.items) - 1]

    def size(self):
        return len(self.items)

    def is_empty(self):
        return self.items == []


class Solution:
    # 匹配符號(hào)直接采用匹配順序
    def match(self, target, test):
        a, b = '{[(', '}])'
        return a.index(target) == b.index(test)

    def isValid(self, s: str) -> bool:
        f = Stack()
        i = 0
        flag = 1
        while i < len(s) and flag == 1:
            # 左邊符號(hào)就放入棧
            if s[i] in '{[(':
                f.push(s[i])
            # 不是左邊符號(hào)猬错,分為兩種情況窗看,要么是右邊符號(hào),要么不符合要求
            else:
                if f.is_empty():
                    flag = 0
                else:
                    top = f.pop()
                    if not self.match(top, s[i]):
                        flag = 0
            i = i + 1

        if f.is_empty() and flag == 1:
            return True
        else:
            return False

  1. 十進(jìn)制轉(zhuǎn)16進(jìn)制 Letcode-405
class Stack:
    def __init__(self):
        self.items = []

    def push(self, item):
        self.items.append(item)

    def pop(self):
        return self.items.pop()

    def peek(self):
        return self.items[len(self.items) - 1]

    def size(self):
        return len(self.items)

    def is_empty(self):
        return self.items == []

class Solution:
    # 匹配符號(hào)直接采用匹配順序
    def toHex(self, num: int) -> str:
        digits = '0123456789abcdef'
        res_stack = Stack()
        if num == 0:
            return '0'
        #采用了反碼的定義
        if num < 0:
            num += 2 ** 32
        
        if num > 0:
            while num > 0:
                rem = num % 16
                res_stack.push(rem)
                num = num // 16

            res = ''
            while not res_stack.is_empty():
                res = res + digits[res_stack.pop()]

            return res
  1. 中綴轉(zhuǎn)前倦炒、后綴表達(dá)式(leetcode 150 && 224 && 227 && 772)
    定義:


    image.png

中綴轉(zhuǎn)后綴


image.png

中綴轉(zhuǎn)前綴


image.png

①leetcode 150 計(jì)算后綴

class Stack:
    def __init__(self):
        self.items = []
    def push(self, item):
        self.items.append(item)

    def pop(self):
        return self.items.pop()

    def peek(self):
        return self.items[len(self.items)-1]

    def size(self):
        return len(self.items)

    def is_empty(self):
        return self.items == []
    
class Solution:
    def evalRPN(self, tokens: List[str]) -> int:
        lst = Stack()
        token = ['/','+','-','*']
        for i in tokens:
            if i not in token:
                lst.push(i)
            else:
                a = lst.pop()
                b = lst.pop()
                # 注意python中負(fù)數(shù)除法與文中不一致显沈,python中-1/2=-1;文中-1/2=0逢唤;引入函數(shù)operator.truediv
                if i == '/':
                    res = int(operator.truediv(int(b),int(a)))
                else:
                    res = eval(b+ i + a)
                lst.push(str(res))
        return int(lst.pop())

②leetcode 224 && 227 && 772 中綴轉(zhuǎn)后綴拉讯,并計(jì)算
首先是個(gè)位數(shù)的加減乘除:

class Stack:
    def __init__(self):
        self.items = []

    def push(self, item):
        self.items.append(item)

    def pop(self):
        return self.items.pop()

    def peek(self):
        return self.items[len(self.items) - 1]

    def size(self):
        return len(self.items)

    def is_empty(self):
        return self.items == []


def middle_to_post(s):
    res_lst = []
    tokens = Stack()
    lst = s.replace(' ', '')
    # 建立順序表
    sequence = {'(': 1, '+': 2, '-': 2, '*': 3, '/': 3, '^': 4}
    for i in lst:
        # 如果是數(shù)字或者字母,直接加入輸出表中
        if i in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' or i in '0123456789':
            res_lst.append(i)
        # 如果是左括號(hào)鳖藕,加入棧中
        elif i == '(':
            tokens.push(i)
        # 右括號(hào)魔慷,則把左括號(hào)前的運(yùn)算符都加到輸出表中,同時(shí)最后的左括號(hào)也刪除
        elif i == ')':
            while tokens.peek() != '(':
                res_lst.append(tokens.pop())
            tokens.pop()
        # 如果是運(yùn)算符
        else:
            # 如果比棧頂?shù)拇笾鳎苯蛹尤霔V?            # 如果小于或等于棧頂院尔,把棧中所有比該運(yùn)算符大或等于的都輸出來(lái)蜻展,加到輸出表中,直到棧頂比它大邀摆,或者空了
            while not tokens.is_empty() and sequence[i] <= sequence[tokens.peek()]:
                res_lst.append(tokens.pop())
            tokens.push(i)

    # 把運(yùn)算符加在后面
    while not tokens.is_empty():
        res_lst.append(tokens.pop())
    return res_lst


# 計(jì)算符纵顾,本來(lái)eval也可以用,但是題目中禁止使用
def do_math(a, b, op):
    if op == '+':
        return a + b
    elif op == '-':
        return a - b
    elif op == '*':
        return a * b
    elif op == '/':
        return a / b
    else:
        return a ** b


# 計(jì)算后綴表達(dá)式
def calculate(s: str) -> int:
    tokens = middle_to_post(s)
    print(tokens)
    # 使用一個(gè)棧用于壓入計(jì)算的數(shù)
    op_stack = Stack()
    for token in tokens:
        if token in '0123456789':
            op_stack.push(int(token))
        elif token in '+-*/^':
            b = op_stack.pop()
            a = op_stack.pop()
            op_stack.push(do_math(a, b, token))

    return op_stack.pop()

思考了下多位數(shù)的情況:224 && 227 && 772均成功AC

class Stack:
    def __init__(self):
        self.items = []

    def push(self, item):
        self.items.append(item)

    def pop(self):
        return self.items.pop()

    def peek(self):
        return self.items[len(self.items) - 1]

    def size(self):
        return len(self.items)

    def is_empty(self):
        return self.items == []


def middle_to_post(s):
    res = []
    res_lst = Stack()
    tokens = Stack()
    lst = s.replace(' ', '')
    print(lst)
    # 建立順序表
    sequence = {'(': 1, '+': 2, '-': 2, '*': 3, '/': 3, '^': 4}
    for i in lst:
        # 如果是數(shù)字或者字母隧熙,直接加入輸出表中
        if i.isdigit():
            if not res_lst.is_empty() and type(res_lst.peek()) is int:
                res_lst.push(res_lst.pop() * 10 + int(i))
            else:
                res_lst.push(int(i))
            continue

        elif not i.isdigit() and len(res_lst.items) >= 1:
            res.append(res_lst.pop())

        # 如果是左括號(hào)片挂,加入棧中
        if i == '(':
            tokens.push(i)
        # 右括號(hào)幻林,則把左括號(hào)前的運(yùn)算符都加到輸出表中贞盯,同時(shí)最后的左括號(hào)也刪除
        elif i == ')':
            while tokens.peek() != '(':
                res.append(tokens.pop())
            tokens.pop()
        # 如果是運(yùn)算符
        else:
            # 如果比棧頂?shù)拇螅苯蛹尤霔V?            # 如果小于或等于棧頂躏敢,把棧中所有比該運(yùn)算符大或等于的都輸出來(lái)件余,加到輸出表中遭居,直到棧頂比它大俱萍,或者空了
            while not tokens.is_empty() and sequence[i] <= sequence[tokens.peek()]:
                res.append(tokens.pop())
            tokens.push(i)

    if len(res_lst.items) >= 1:
        res.append(res_lst.pop())
    # 把運(yùn)算符加在后面
    while not tokens.is_empty():
        res.append(tokens.pop())

    return res


# 計(jì)算符,本來(lái)eval也可以用损谦,但是題目中禁止使用
def do_math(a, b, op):
    if op == '+':
        return a + b
    elif op == '-':
        return a - b
    elif op == '*':
        return a * b
    elif op == '/':
        return a / b
    else:
        return a ** b


# 計(jì)算后綴表達(dá)式
def calculate(s: str) -> int:
    tokens = middle_to_post(s)
    print(tokens)
    # 使用一個(gè)棧用于壓入計(jì)算的數(shù)
    op_stack = Stack()
    for token in tokens:
        if isinstance(token, (int, list)):
            op_stack.push(token)
        elif token in '+-*/^':
            b = op_stack.pop()
            a = op_stack.pop()
            op_stack.push(do_math(a, b, token))

    return op_stack.pop()
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市话侧,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌瞻鹏,老刑警劉巖乙漓,帶你破解...
    沈念sama閱讀 221,273評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件叭披,死亡現(xiàn)場(chǎng)離奇詭異玩讳,居然都是意外死亡熏纯,警方通過(guò)查閱死者的電腦和手機(jī)粤策,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)秩贰,“玉大人毒费,你說(shuō)我怎么就攤上這事愈魏。” “怎么了溪厘?”我有些...
    開(kāi)封第一講書人閱讀 167,709評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵畸悬,是天一觀的道長(zhǎng)傻昙。 經(jīng)常有香客問(wèn)我,道長(zhǎng)妆档,這世上最難降的妖魔是什么贾惦? 我笑而不...
    開(kāi)封第一講書人閱讀 59,520評(píng)論 1 296
  • 正文 為了忘掉前任须板,我火速辦了婚禮兢卵,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘甜奄。我一直安慰自己,他們只是感情好牍氛,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,515評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布烟阐。 她就那樣靜靜地躺著蜒茄,像睡著了一般。 火紅的嫁衣襯著肌膚如雪楔敌。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 52,158評(píng)論 1 308
  • 那天胜臊,我揣著相機(jī)與錄音伙判,去河邊找鬼。 笑死勒魔,一個(gè)胖子當(dāng)著我的面吹牛菇曲,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播弟胀,決...
    沈念sama閱讀 40,755評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼孵户,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼岔留!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起竖配,我...
    開(kāi)封第一講書人閱讀 39,660評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎械念,沒(méi)想到半個(gè)月后龄减,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體希停,經(jīng)...
    沈念sama閱讀 46,203評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,287評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了违崇。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片羞延。...
    茶點(diǎn)故事閱讀 40,427評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖入愧,靈堂內(nèi)的尸體忽然破棺而出棺蛛,到底是詐尸還是另有隱情巩步,我是刑警寧澤,帶...
    沈念sama閱讀 36,122評(píng)論 5 349
  • 正文 年R本政府宣布彤恶,位于F島的核電站声离,受9級(jí)特大地震影響术徊,放射性物質(zhì)發(fā)生泄漏赠涮。R本人自食惡果不足惜子寓,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,801評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望垃它。 院中可真熱鬧,春花似錦洛史、人聲如沸酱吝。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,272評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)霎褐。三九已至该镣,卻和暖如春损合,著一層夾襖步出監(jiān)牢的瞬間嫁审,已是汗流浹背律适。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,393評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工遏插, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人厂僧。 一個(gè)月前我還...
    沈念sama閱讀 48,808評(píng)論 3 376
  • 正文 我出身青樓颜屠,卻偏偏與公主長(zhǎng)得像甫窟,于是被迫代替她去往敵國(guó)和親粗井。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,440評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容