2.Python数据结构与算法 2.2算法和数据结构

栈的定义

在这里插入图片描述
对于栈,不用关心它在物理上是怎么存放的,关心这种数据结构支持什么操作?操作有什么特点?
类似于杯子,只有一个口,这种结构,先加的数据先到达杯底,取出数据时杯口的先出。

保存的数据如何存放?

  1. a1到an数据用顺序表存储,顺序表的特点就是连续存放一组数据,只要在栈中封装顺序表时,保证使用时只能从一端添加和取出,另外一端不允许访问,

  2. 用链表
    使用时链表只能在链表的尾部访问数据,虽然之前在写链表时支持头部访问,现在我将头部访问禁止,只允许尾部添加append,尾部删除,这样这个链表就是一个栈。

  3. 所以顺序表和链表解决的是数据怎么存放的问题,在顺序表和链表中封装了一系列方法,但是把头部方法禁止后,只允许从尾部访问数据,即只允许一端,这样顺序表或者链表都变为栈,
    所以栈和顺序表即链表的区别在于,顺序表和链表描述的是怎么存放数据,栈描述的是如何访问数据(方法).

  4. 什么时候用到栈?
    比如一个数学表达式 1*(2+3) 可以用栈的方式去解析

栈的实现

用顺序表来写
在python中,列表就是顺序表,用list实现栈

  1. 栈的操作
    在这里插入图片描述
    往栈中添加元素叫做压栈/入栈,英文是push
    出栈,弹出,pop
    peek(窥视,偷看,探出),返回栈中元素,但是元素还在栈中
    以上为要封装的栈的ADT类型

  2. 写一个栈的类
    注意写的过程
    先写出类名:
    在这里插入图片描述
    再将已经计划要写的类的方法给放进去,作为写代码的蓝本
    在这里插入图片描述
    将这些方法写规范
    在这里插入图片描述
    对于栈来说,要定义以上几种方法,使用:构造栈的对象,往里面加元素,
    类的属性还没定义,类的对象是什么,在栈中如何存入元素,要生成栈的容器:将这个容器封装为私有东西,不希望操作栈的人直接操作内部的容器,开始时没有任何元素,所以容器为空
    在这里插入图片描述

  3. 栈代码

class Stack(object):
    """栈"""
    def __init__(self):
         #self.__list #合理,但是这样写,就可以用这个命令直接拿到我的全部列表
         return self.__list = []

    def is_empty(self):
        """判断是否为空"""
        return self.__list == [] # self.__list == [],[]为空值,判断左右两边是否相等,返回结果为布尔值。这行代码简写了

    def push(self, item):
        """添加一个新的元素item到栈顶"""
        self.__list.append(item)

    def pop(self):
        """弹出栈顶元素"""
        return self.__list.pop() #不写return,单纯self.__list.pop()的返回值是none
#同上面对比,选择在尾部不选择在头部添加弹出的原因,顺序表在尾部操作的时间复杂度是O(1),操作头部的时间复杂度是O(n)。
#用单链表存,就要从头部操作元素
# 所以根据存储容器不同,时间复杂度不同
     #def push(self, item):
      #   self.__list.insert(0,item)
     #def pop(self, item):
      #   self.__list.pop(0)

    def peek(self):
        """返回栈顶元素""" 
        if self.__list:            
            return self.__list[-1] #列表为空,不支持访问操作,要设置判断条件
        else:
            return None

    def size(self):
        """返回栈的大小"""
        return len(self.__list)

if __name__ == "__main__":
    s = Stack()
    s.push(1)
    s.push(2)
    s.push(3)
    s.push(4)
    print(s.pop())
    print(s.pop())
    print(s.pop())
    print(s.pop())

之所以简单,是对已有存储结构的二次开发
运行结果如下:压进去是1,2,3,4,pop出来是4,3,2,1
在这里插入图片描述

队列

队列的定义

在这里插入图片描述
顺序表和链表都可以通过禁用某些方法来实现队列的操作。

所以顺序表和链表解决存储,在具体使用时要关注容器的具体操作特性,是FIFO还是LIFO

队列的实现

在这里插入图片描述
实现代码的思路和栈一样

class Queue(object):
    """队列"""
    def __init__(self):
        self.__list = []

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

    def enqueue(self, item):
        """进队列"""
        self.__list.insert(0,item) #在list头部添加元素
       #self.__list.append(item) #在list尾部添加元素
    def dequeue(self):
        """出队列"""
        return self.__list.pop() #从list尾部弹出
        return self.__list.pop(0)#从list头部弹出
# 选用那个,要看经常用的是进队还是出队,再考虑不同操作的时间复杂度
    def size(self):
        """返回大小"""
        return len(self.__list)

if __name__ == "__main__"
    s = Queue()
    s.enqueue(1)
    s.enqueue(2)
    s.enqueue(3)
    s.enqueue(4)
    print(s.dequeue())
    print(s.dequeue())
    print(s.dequeue())
    print(s.dequeue())

队列的扩展—双端队列

在这里插入图片描述

双端队列实现

class Deque(object):
    """双端队列"""
    def __init__(self):
        self.__list = []

    def is_empty(self):
        """判断队列是否为空"""
        return self.__list == []

    def enqueue_front(self, item):
        """在队头添加元素"""
        self.__list.insert(0,item)

    def enqueue_rear(self, item):
        """在队尾添加元素"""
        self.__list.append(item)

    def dequeue_front(self):
        """从队头取出元素"""
        return self.__list.pop(0)

    def dequeue_rear(self):
        """从队尾取出元素"""
        return self.__list.pop()

    def size(self):
        """返回队列大小"""
        return len(self.__list)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值