【问题标题】:Creating a Queue Class创建队列类
【发布时间】:2020-09-22 11:32:20
【问题描述】:

我正在尝试使用具有入队、出队和长度功能的链接实现来实现队列类。据我对队列的理解,当第一次实现时,队列指向最初指向无的头和尾节点。随着项目被添加到队列中,一个节点指向该项目,头节点保持不变,而尾节点指向新项目。

我尝试在 python 中使用以下代码来实现这一点,但它似乎不起作用。我不确定是我的逻辑错了,还是代码错了,或者两者兼而有之?

class Queue:
    def __init__(self, data=None):
        # Initialize this queue, and store data if it exists
        self.data = data
        self.head = None
        self.tail = None
        self.node = None
        self.length = 0

    def enqueue(self, data):              
        if self.head == None:
            self.head = Queue(data)
            self.tail = self.head
        else:
            self.node = data
            self.tail = self.node
            data = self.data
        self.length += 1

    def dequeue(self):
        item = self.head.item
        self.head = self.head.next
        self.length -= 1
        return item

    def __len__(self):
        return self.length

【问题讨论】:

  • self.head.item 和 self.head.next 定义在哪里?另外,我认为您不需要在类方法中声明类的实例

标签: python queue deque enqueue


【解决方案1】:

我会避免在类的定义中声明类的实例。在我看来,声明 self.head = Queue(data) 是自找麻烦,因为这可能导致声明 self.head.head 和 self.head.head.head... 你明白了。相反,我可能会把事情分开一点。另外,请注意您没有声明 self.head.next 或 self.head.item,即使您在方法中调用了它们。

也许声明两个类,一个用于节点,另一个用于由节点构建的队列?这会简化一些事情。

以下是我在 Python 中构建队列的方法,请相信我自己:

from typing import Iterable

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

    def __call__(self):
        return self.data

class Queue:
    def __init__(self, x=None):
        assert isinstance(x, Node) or (x == None) or isinstance(x, Iterable)
        if isinstance(x, Iterable):
            self.head = Node(x[0])
            self.tail = Node(x[0])
            self.length = 1
            self.to_queue(x[1:])
        else:
            self.head = x
            self.tail = x
            self.length = 1 if x else 0

    def enqueue(self, data):
        tmp = self.head
        self.head = Node(data)
        self.head.next = tmp
        self.length += 1

    def dequeue(self):
        if self.length <= 0:
            print("empty Queue")
            return
        tmp = self.head
        for i in range(self.length-2):
            tmp = tmp.next
        self.tail = tmp
        self.tail.next = None
        self.length -= 1
        if self.length == 0:
            self.head = None
            self.tail = None

    def to_queue(self, vals):
        for i in vals:
            self.enqueue(i)

    def __call__(self):
        tmp = self.head
        while (tmp):
            print(tmp.data, end=" ")
            tmp = tmp.next

    def __len__(self):
        return self.length

请注意,这对于生产代码来说都是不必要的,因为您可以只使用deque,例如,来自collections module

【讨论】:

    【解决方案2】:

    另一种方法是将队列实现为两个堆栈:

    class Stack():
        def __init__(self):
            self.items = []
        def push(self, item):
            self.items.append(item)
        def pop(self):
            if len(self.items) == 0:
                raise IndexError("Can't pop from an empty stack!")
            return self.items.pop(len(self.items) - 1)
        def isEmpty(self):
            return len(self.items) == 0
    
    class Queue():
        def __init__(self):
            self.stack1 = Stack()
            self.stack2 = Stack()
        def enqueue(self, item):
            self.stack1.push(item)
        def dequeue(self):
            if self.stack2.isEmpty():
                while not self.stack1.isEmpty():
                    self.stack2.push(self.stack1.pop())
            return self.stack2.pop()
        def isEmpty(self):
            return self.stack1.isEmpty() and self.stack2.isEmpty()
    

    但我同意其他答案,对于任何严肃的项目,标准库及其collections 模块应该是首选。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-01-17
      • 1970-01-01
      • 1970-01-01
      • 2012-12-10
      • 2016-08-18
      • 2010-11-12
      • 2011-06-21
      • 2021-10-07
      相关资源
      最近更新 更多