【数据结构与算法基础】队列、栈、递归

栈(Stack)

定义
  • 栈是一种容器,其中添加移除新项总发生在同一端。这一端通常称为“顶部”。与顶部对应的端称为“底部”。
  • 最重要特性:先进后出。这一特性让栈拥有反转元素顺序的功能。如下图:
用数组实现一个顺序栈
  • Python的list及其操作可以提供与栈的使用方式有关的功能,可以使用list来实现栈。这里我们默认list末尾为栈顶。
class Stack:
     def __init__(self):
         self.items = []

     def isEmpty(self):
         return 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)
用链表实现一个链式栈
  • 为什么需要链式栈?

主要考虑顺序表的两个特点:1)扩大存储需要一次高代价操作;2)顺序表需要完整的大块存储区。

  • 链式栈自然就以表头为栈顶
class ListNode:

    def __init__(self, elem, next=None):
        self.elem = elem
        self.next = next

class LStack():
    def __init__(self):
        self._top = None

    def isEmpty(self):
        return self._top is None

    def push(self, elem):
        self._top = ListNode(elem, self._top)

    def pop(self):
        if self._top is None:
            raise ValueError('wrong in pop!')
        p = self._top
        self._top = p.next
        return p.elem

    def peek(self):
        if self._top is None:
            raise ValueError('wrong in peek!')
        return self._top.elem

    def __repr__(self) -> str:
        cur = self._top
        nums = []
        while cur:
            nums.append(cur._data)
            cur = cur._next
        return "--> ".join(f"{num}" for num in nums)

if __name__ == '__main__':
    stack = LStack()
    for i in range(10):
        stack.push(i)
    print(stack)
编程模拟实现一个浏览器的前进、后退功能
class Browser():

    def __init__(self):
        self.x = LStack()  # 前进
        self.y = LStack()  # 后退

    def view(self, page):
        print('Viewing %s' % page, end='\n')
        self.x.push(page)

    def forward(self):
        if self.y.isEmpty():
            print( 'can not forward!')
            return 
        top = self.y.pop()
        self.x.push(top)
        print('go to %s' % top, end='\n')

    def backward(self):
        if self.x.isEmpty():
            print('can not backward!')
            return
        top = self.x.pop()
        self.y.push(top)
        print('back to %s' % top, end='\n')

    def can_forward(self):
        if self.y.isEmpty():
            return False
        return True

    def can_back(self):
        if self.x.isEmpty():
            return False
        return True

if __name__ == '__main__':
    b = Browser()
    for i in ['a', 'b', 'c']:
        b.view(i)
    while b.can_back():
        b.backward()

    while b.can_forward():
        b.forward()
    b.forward()
Leetcode栗子

队列(Queue)

定义
  • 队列也是一种容器,其中最重要的特性就是先进先出。如下图:
用链表实现一个链式队列
  • 最简单的单链表实现的话只能完成O(1)时间复杂度的enqueue操作和O(N)时间复杂度的dequeue操作,所以基于单链表的实现不太高效
  • 如果要实现首尾都是O(1)的话,我们可以尝试双向链表
用数组实现一个顺序队列
  • 基于python的list实现顺序队列,最直接的实现方法入队采取append(),出队采取pop(0),这样就得到一个O(1)时间复杂度的enqueue操作和O(N)时间复杂度的dequeue操作。
实现循环队列
  • 前面说的顺序队列显然不够高效,如果我们要实现所有操作都是O(1)时间,可以再设置一个指针,记住队头的位置,当出队操作完成后,更新队头指针。
  • 基于上述思想,同时为了防止内存空置消耗,可以采用循环队列的实现。
# coding=utf-8
# @author: kaiyuan
# blog: https://blog.csdn.net/Kaiyuan_sjtu
from itertools import chain

class CirQueue:

    def __init__(self, capacity):
        self._items = []
        self._capacity = capacity + 1
        self._head = 0
        self._rear = 0

    def enqueue(self, elem):
        if (self._rear + 1) % self._capacity == self._head:
            return False
        self._items.append(elem)
        self._rear = (self._rear + 1) % self._capacity
        return True

    def dequeue(self):
        if self._head != self._rear:
            item = self._items[self._head]
            self._head = (self._head + 1) % self._capacity
            return item

    def __repr__(self):
        if self._rear >= self._head:
            return " ".join(item for item in self._items[self._head: self._rear])

        else:
            return " ".join(item for item in chain(self._items[self._head:], self._items[:self._rear]))

if __name__ == '__main__':
    cq = CirQueue(10)
    for i in range(10):
        cq.enqueue(str(i))
    print(cq)
    for i in range(5):
        cq.dequeue()
    print(cq)
队列栗子

递归

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值