python实现==简单队列==

文章介绍了队列数据结构的概念,遵循先进先出(FIFO)原则,并提供了两种Python实现:顺序表和链表。顺序表通过列表实现,利用append方法添加元素,pop方法移除元素。链表实现中,头节点表示队首,尾节点表示队尾,特别处理了单元素链表的pop操作。文章附有完整代码示例。
摘要由CSDN通过智能技术生成

队列


什么是队列?

队列(Queue)是一种常见的数据结构,它遵循先进先出(First-In-First-Out,FIFO)的原则。简单来说,队列就像是一个排队等候的人群,新的元素被添加到队列的末尾,而从队列中移除元素时,总是从队列的前端进行。
在这里插入图片描述


队列的特点

  • 队尾入队
  • 队首出队

两种线性表结构实现队列(附件中均附有源码)

队列实现的操作

队列实现的操作


python顺序表实现队列

创建一个空的队列

class Queue:
    def __init__(self):
        self.item = []

判断队列是否为空和返回元素个数

class Queue:
    def __init__(self):
        self.item = []

    def is_empty(self):
        return  self.length() == 0

    def length(self):
        return len(self.item)

添加一个元素到队尾

因为是用顺序表结构实现队列,也就是列表,那么这里就要考虑将列表的第一个元素作为队首还是队尾

添加一个元素到队尾 用append方法,因为insert方法时间复杂度为O(n),而append方法的时间复杂度为O(1)

def push(self,data):
    '''添加一个元素到队尾  用append方法,因为insert方法时间复杂度为O(n)'''
    self.item.append(data)

弹出队头

将队头从队列中踢出,并返回队头元素

同样的,我们使用列表的pop方法来删除并返回指定的元素。

但是值得注意的是,pop方法在列表元素为空的时候(也就是找不到指定的索引元素的时候)会报错,这个时候我们手动抛出异常

    def pop(self):
        if self.is_empty():
            raise  ValueError('队列为空')
        return self.item.pop(0)

获取队头

仅仅是返回队头元素,并不删除队头元素

def peek(self):
    if self.is_empty():
        raise  ValueError('队列为空')
    return self.item[0]

pyhton链式表实现队列

简单操作如下

class Node():
    def __init__(self,data,next = None):
        self.data = data
        self.next = next

class Queue:
    '''
    链表的第一个元素是队列的头部,链表的最后一个元素是对列的尾部
    '''
    def __init__(self):
        self.head = None
        self.rear = None
        self.lenth = 0

    def is_empty(self):
        return  self.lenth == 0

    def length(self):
        return self.lenth

添加一个元素data到队列尾部

  1. 创建一个新的结点
  2. 将新的结点添加到链表的尾部(链表的尾部既队列的尾部)
  3. 将原来的尾结点的next属性指向新的结点
  4. 将队列的rear(原来的尾结点)属性指向新的结点
  5. 队列长度加1
  6. 特殊情况下:
    如果链表为空
    那么就是添加到链表的头部 具体操作如下:
    1.将队列的head属性指向新的结点
    2.将队列的rear属性指向新的结点 (因为在空的队列中台添加一个对象那么这个对象既是队首又是队尾)
 def push(self,data):
        node = Node(data)    # 创建一个新的结点
        if self.is_empty():    #特殊情况
            self.head = node
            self.rear = node
        else:
            self.rear.next = node # 将原来的尾结点的next属性指向新的结点
            self.rear = node      # 将队列的rear(原来的尾结点)属性指向新的结点
        self.lenth += 1

抛出队首元素

原版代码(原版代码没有错,只是有点漏洞,但是不会影响程序的正常运行)

队首元素也就是链表的第一个结点

  1. 创建一个变量指向头节点(用于后续的返回)
  2. 将链表的head属性指向原来头节点的下一个结点
def pop(self):
    if self.is_empty():
        raise  ValueError('队列为空')
    value = self.head.data
    self.head = self.head.next
    # print(f'队列的头部结点是{self.rear.data}')
    self.lenth -= 1
    return value

这里我们来思考一种特殊的情况====>>>

当链表中只有一个元素的时候,head属性和rear属性指向的都是第一节点,那么这个时候执行pop方法的时候头节点指向下一个结点(self.head = self.head.next),但是尾结点呢?我们并没有用代码改正尾结点的指向,是不是尾结点还是指向原来的头结点(也就是被我们删掉的那个结点)?是不是我们是使用self.rear.data能够直接访问到被删除结点的值?

我们做个实验验证以下,将上述代码的第六行解除注释运行以下试试看

'''
运行代码如下
'''
if __name__ == '__main__':
    queue = Queue()
    queue.push(1)
    print(queue.pop())
    print(f'队列的头部结点是{queue.rear.data}')

运行结果如图所示
在这里插入图片描述

可见在外部和内部进行访问的时候访问到的都是原来的值,其rear并未指向None。

改进代码如下:
    def pop(self):
        '''抛出队首元素也就是链表的第一个结点'''
        '''
        创建一个变量指向头节点(用于后续的返回)
        将链表的head属性指向原来头节点的下一个结点
        '''
        if self.is_empty():
            raise  ValueError('队列为空')
        value = self.head.data
        if self.lenth == 1:
            self.head = None
            self.rear = None
            # print(f'队列的头部结点是{self.rear}')
        else:
            self.head = self.head.next
            self.lenth -= 1
        return value

返回队首元素

返回头节点的值即可

    def peek(self):
        if self.is_empty():
            raise  ValueError('队列为空')
        return self.head.data

附件

附件1:顺序表实现队列的完整代码

# @Author  :泰敢人辣
# Date     :2023-07-29 17:46

'''用python实现队列'''
class Queue:
    def __init__(self):
        self.item = []

    def is_empty(self):
        return  self.length() == 0

    def length(self):
        return len(self.item)

    def push(self,data):
        '''添加一个元素到队尾  用append方法,因为insert方法时间复杂度为O(n)'''
        self.item.append(data)

    def pop(self):
        if self.is_empty():
            raise  ValueError('队列为空')
        return self.item.pop(0)

    def peek(self):
        if self.is_empty():
            raise  ValueError('队列为空')
        return self.item[0]

if __name__ == '__main__':
    queue = Queue()
    queue.pop()

附件2:链表实现队列的完整代码

# @Author  :泰敢人辣
# Date     :2023-07-29 18:17

'''用链表实现队列'''

# 定义结点类
class Node():
    def __init__(self,data,next = None):
        self.data = data
        self.next = next

class Queue:
    '''
    链表的第一个元素是队列的头部,链表的最后一个元素是对列的尾部
    '''
    def __init__(self):
        self.head = None
        self.rear = None
        self.lenth = 0

    def is_empty(self):
        return  self.lenth == 0

    def length(self):
        return self.lenth

    def push(self,data):
        '''
        添加一个元素data到队列尾部
        创建一个新的结点
        将新的结点添加到链表的尾部(链表的尾部既队列的尾部)
            将原来的尾结点的next属性指向新的结点
            将队列的rear(原来的尾结点)属性指向新的结点
        队列长度加1
        特殊情况下:
        如果链表为空
        那么就是添加到链表的头部  具体操作如下:
        1.将队列的head属性指向新的结点
        2.将队列的rear属性指向新的结点 (因为在空的队列中台添加一个对象那么这个对象既是队首又是队尾)
        '''
        node = Node(data)
        if self.is_empty():
            self.head = node
            self.rear = node
        else:
            self.rear.next = node # 将原来的尾结点的next属性指向新的结点
            self.rear = node      # 将队列的rear(原来的尾结点)属性指向新的结点
        self.lenth += 1


    def pop(self):
        '''抛出队首元素也就是链表的第一个结点'''
        '''
        创建一个变量指向头节点(用于后续的返回)
        将链表的head属性指向原来头节点的下一个结点
        '''
        if self.is_empty():
            raise  ValueError('队列为空')
        value = self.head.data
        if self.lenth == 1:
            self.head = None
            self.rear = None
            # print(f'队列的头部结点是{self.rear}')
        else:
            self.head = self.head.next
            self.lenth -= 1
        return value

    def peek(self):
        if self.is_empty():
            raise  ValueError('队列为空')
        return self.head.data


if __name__ == '__main__':
    queue = Queue()
    queue.push(1)
    queue.push(2)
    queue.push(3)
    queue.push(4)
    print(queue.peek())
    print(queue.pop())
    print(queue.pop())
    print(queue.pop())
    print(queue.pop())
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TAGRENLA

您的打赏是我创作的动力,谢谢!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值