Stack与Queue

Stack

image.png

由于堆栈数据结构只允许在一端进行操作,因而按照后进先出(LIFO, Last In First Out)的原理运作。实现方式主要有顺序栈和链栈

基本操作:
  init: -> Stack
  push: N x Stack -> Stack
  top: Stack -> (N U ERROR)
  pop: Stack -> Stack
  isempty: Stack -> Boolean
一、先看LeetCode 155. Min Stack
  • 顺序栈, 使用python的list实现
class MinStack(object):

    def __init__(self):
        """
        initialize your data structure here.
        """
        self.data = []

    def push(self, x):
        """
        :type x: int
        :rtype: void
        """
        self.data.append(x)

    def pop(self):
        """
        :rtype: void
        """
        if self.data:
            self.data.pop(-1)
        
    def top(self):
        """
        :rtype: int
        """
        if self.data:
            return self.data[-1]
        
    def getMin(self):
        """
        :rtype: int
        """
        if self.data:
            return min(self.data)
  • 链栈,由于栈操作只在一断操作,可以用单链表采用头插法实现
class Node(object):
    def __init__(self, x):
        self.val = x
        self.next = None
        self.pre = None


class MinStack(object):

    def __init__(self):
        """
        initialize your data structure here.
        """
        self.head = Node(None)

    def push(self, x):
        """
        :type x: int
        :rtype: void
        """
        node = Node(x)
        if self.head.next:
            node.next = self.head.next
            self.head.next = node
        else:
            self.head.next = node

    def pop(self):
        """
        :rtype: void
        """
        if self.head.next:
            self.head.next = self.head.next.next
        
    def top(self):
        """
        :rtype: int
        """
        if self.head.next:
            return self.head.next.val
        
    def getMin(self):
        """
        :rtype: int
        """
        p = self.head.next
        min = float('inf')
        while p:
            if min > p.val:
                min = p.val
            p = p.next
        return min

可以看到getMin函数需要的时间复杂度是O(n),如果要降低getMin的时间复杂度,可以每个数据元存储当前值加当前最小值,需要空间复杂度O(n)

Queue

image.png

先进先出(FIFO, First-In-First-Out)的线性表。在具体应用中通常用链表或者数组来实现。队列只允许在后端(称为rear)进行插入操作,在前端(称为front)进行删除操作。
那么如何用链表实现一个队列呢,首先队列是双端操作,涉及到出队的时候需要删除尾节点,如果用单链表的话每次删除都是O(n)的操作,所以用双向链表实现,可以控制删除操作为O(1)

class ListNode(object):
    def __init__(self, x):
        self.val = x
        self.next = None
        self.pre = None

class Queue(object):
    def __init__(self):
        self.tail = ListNode(None)
        self.head = ListNode(None)
        self.tail.next = self.head
        self.head.next = self.tail

    def enqueue(self, item):
        cur_node = ListNode(item)
        if self.head.next == self.tail:
            self.head.next = cur_node
            self.tail.next = cur_node
            cur_node.pre = self.head
            cur_node.next = self.tail
        else:
            pre_node = self.head.next
            self.head.next = cur_node
            pre_node.pre = cur_node
            cur_node.pre = self.head

    def dequeue(self):
        cur_node = self.tail.next
        pre_node = cur_node.pre
        if cur_node == self.head:
            return
        self.tail.next = pre_node
        pre_node.next = self.tail
        return cur_node.val

    def empty(self):
        return self.head.next == self.tail
二、LeetCode 225. Implement Stack using Queues

用队列实现栈,这里先用list实现一个队列FIFO,根据栈的特性FILO,
所以用两个队列,入栈的操作直接压入有数据的队列,当出栈是直接把有数据的队列依次pop到另一个空队列,当剩下最后一个数据即栈顶元素

class Queue(object):
    def __init__(self):
        self.data = []
        
    def pop(self):
        if self.data:
            return self.data.pop(0)
    
    def push(self, x):
        self.data.append(x)
    
    def tail(self):
        if self.data:
            return self.data[-1]
    
    def empty(self):
        if self.data:
            return False
        return True


class MyStack(object):

    def __init__(self):
        """
        Initialize your data structure here.
        """
        self.queue_a = Queue()
        self.queue_b = Queue()
        
    def push(self, x):
        """
        Push element x onto stack.
        :type x: int
        :rtype: void
        """
        q = self.queue_b if self.queue_a.empty() else q = self.queue_a
        q.push(x)

    def pop(self):
        """
        Removes the element on top of the stack and returns that element.
        :rtype: int
        """
        if not self.queue_a.empty():
            sour_q = self.queue_a
            dest_q = self.queue_b
        else:
            dest_q = self.queue_a
            sour_q = self.queue_b
        while not sour_q.empty():
            data = sour_q.pop()
            if sour_q.empty():
                return data
            dest_q.push(data)
            
    def top(self):
        """
        Get the top element.
        :rtype: int
        """
        q = self.queue_b if self.queue_a.empty() else q = self.queue_a
        return q.tail()
        
    def empty(self):
        """
        Returns whether the stack is empty.
        :rtype: bool
        """
        return self.queue_a.empty() and self.queue_b.empty()
三、LeetCode 232. Implement Queue using Stacks

根据队列FIFO和栈FILO的特性,使用两个栈的话,一个栈专入数据stack_in,一个栈专出数据stack_out,所有数据走stack_out出,即实现队列

class Stack(object):
    def __init__(self):
        self.data = []
    
    def push(self, x):
        self.data.append(x)
    
    def pop(self):
        if self.data:
            return self.data.pop(-1)
        
    def empty(self):
        if self.data:
            return False
        return True
    
    def buttom(self):
        if self.data:
            return self.data[0]

class MyQueue(object):

    def __init__(self):
        """
        Initialize your data structure here.
        """
        self.stack_in = Stack()
        self.stack_out = Stack()
        
    def push(self, x):
        """
        Push element x to the back of queue.
        :type x: int
        :rtype: void
        """
        self.stack_in.push(x)

    def pop(self):
        """
        Removes the element from in front of queue and returns that element.
        :rtype: int
        """
        if self.stack_out.empty():
            while not self.stack_in.empty():
                data = self.stack_in.pop()
                self.stack_out.push(data)
        return self.stack_out.pop()

    def peek(self):
        """
        Get the front element.
        :rtype: int
        """
        if self.stack_out.empty() and not self.stack_in.empty():
            return self.stack_in.data[0]
        else:
            return self.stack_out.data[-1]

    def empty(self):
        """
        Returns whether the queue is empty.
        :rtype: bool
        """
        return self.stack_in.empty() and self.stack_out.empty()
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,029评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,395评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,570评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,535评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,650评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,850评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,006评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,747评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,207评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,536评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,683评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,342评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,964评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,772评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,004评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,401评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,566评论 2 349

推荐阅读更多精彩内容