【问题标题】:Python 3: Popping from the front and end of a Node based Deque in O(1) timePython 3:在 O(1) 时间内从基于节点的双端队列的前端和后端弹出
【发布时间】:2017-09-30 16:40:05
【问题描述】:

(我搜索了 2 个多小时的解决方案,但找不到任何我需要的示例代码)

大家好,我创建了一个 Queue 类和一个继承 Queue 的 Deque 类。我用来构建这些结构的 Node 类初始化为 2 个字段:item 和 next。

我试图让我的 Deque 类在 O(1) 时间内从两端出列,但我的问题是下一个指针只指向一个方向。我可以通过将 next 指针设置为我创建的 new_node 轻松地将项目添加到 Deque 的末尾,并且我可以通过将 Deque 的头部设置为我的 new_node 来轻松地将项目添加到前面,然后说下一个项目是老头。

我什至可以通过说 head = head.next 轻松地从前面删除项目

我的问题:我无法从 Deque 的 REAR 中删除项目,因为如果我删除它,我最后的指针将指向任何内容。我不能说 tail = tail.next,因为那没有任何意义。

我不知道我怎么会遇到这样一个看似简单的问题,但我终其一生都无法弄清楚该怎么做。

我错过了什么/没有考虑到什么??

我的问题代码位于我所提供内容的最底部,但如果您想阅读其余部分,请随意阅读!

class Node:

    def __init__(self, value):
        self.item = value
        self.next = None

    def get_value(self):
        return self.item

    def set_value(self, value):
        self.item = value

    def get_next(self):
        return self.next

    def set_next(self, other_node):
        self.next = other_node


class Queue:

    def __init__(self):
        self.size = 0
        self.head = None
        self.tail = None

    def is_empty(self):
        if self.size == 0:
            return True
        else:
            return False

    def peek(self):
        return self.head.item

    def enqueue(self, value):
        new_node = Node(value)
        if self.isEmpty():
            self.tail = new_node
            self.head = self.tail
            self.size += 1

        else:
            self.tail.next = new_node
            self.tail = new_node
            self.size += 1

    def dequeue(self):
        if self.is_empty():
            raise IndexError('Can not dequeue from an empty queue')
        else:
            value = self.head.item
            self.head = self.head.next
            self.size -= 1
        return value

    def printout(self):
        if self.is_empty():
            return 'Queue is empty'

        else:
            temp = self.head
            while temp is not self.tail:
                print('[ {} ] -> '.format(temp.item), end='')
                temp = temp.next
            print('[ {} ]'.format(self.tail.item))


class Deque(Queue):

    def __init__(self):
        super().__init__()

    def peek_back(self):
        return self.tail.item

    def enqueue_front(self, value):
        new_node = Node(value)
        if self.is_empty():
            self.head = new_node
            self.tail = self.head
            self.size += 1
        else:
            temp = self.head
            self.head = new_node
            self.head.next = temp
            self.size += 1

    def dequeue_back(self):
        if self.is_empty():
            raise IndexError
            # ??????
            # ??????

【问题讨论】:

  • 您是否考虑在您的Node 类中添加一个self.previous 变量来指向前面的节点(如果有的话)?
  • 是的,这绝对是一个选项,但我想知道是否有一种方法可以仅使用 next 指针和 Queue 类中提供的内容。基本上是在不修改我的 Node 类的情况下让它工作
  • 您如何使用与原始队列具有相同元素但被翻转的单独队列(即原始队列中的第一个元素将成为最后一个元素,但其self.next 将指向任何内容,原始队列中的第二个元素将成为倒数第二个元素,其self.next 指向现在的最后一个元素,依此类推)以跟踪原始队列中每个元素的前一个元素是什么?如果不清楚,请告诉我。
  • 非常有趣。感谢您的回复肖恩!

标签: python python-3.x linked-list queue deque


【解决方案1】:

你需要一个双向链表来实现你在O(1)中的目标。

您可以将Node class 子类化并添加指向前一个节点的指针,然后在您的Deque class 中使用它。

或者,正如 cmets 中所指出的,您可以使用两个单链表(第二个反向链接),但这似乎不太实用。

【讨论】:

  • 谢谢,我想我真正遇到的根本问题是,我使用的单链表结构是否可以做到这一点。我有一种感觉,我必须使用双向链表来实现 O(1) 的性能时间。这证实了它
  • 我现在有另一个问题:如果我更改 Deque 的节点,我是否能够使用继承的 enqueue 方法,尽管它与前一个指针没有任何关系?
【解决方案2】:

正如 cmets 中的 Sean 所述,一种解决方案是将 previous 实例变量添加到您的 Node 类中。这是实用的建议方法。

但是,由于您坚持使用专门使用 next 的想法,您可以执行以下操作。由于您使用size 跟踪队列的大小,假设队列不为空,您可以获得倒数第二个元素并将尾部设置为指向它(从后面删除)的唯一方法是:

next_to_last = self.head
for _ in range(self.size - 1):
    next_to_last = next_to_last.next
self.tail = next_to_last

虽然这在内存方面很好(仅存储本地 next_to_last 变量,但它不是 O(1) 操作。

另一个建议是为 Queue 和 Dequeue 创建单独的 Node 类;可能将 Node 类 存储在 队列类本身中:

class Queue:
    class Node:
        # ...

class Dequeue:
    class Node:
        # ...

使用这种方法,您可以在 Dequeue 的 Node 类中定义 self.prev,但不能在常规 Queue 的 Node 类中定义。

【讨论】:

  • 很有趣,我从来没有想过在一个类中使用一个类。谢谢你的意见,你给了我一些非常有趣的想法。
  • @ZachKing,其实是O(N)操作,我想你的意思是“这不是O(1)操作”
  • 是的@ReblochonMasque 感谢您指出这一点。我已经更新了我的答案以纠正错字。
  • 您也可以只拥有一个单独的 Node 类并创建一个继承自 NodeDequeNode 类,正如 Reblochon Masque 的回答中所指出的那样。
猜你喜欢
  • 2017-04-04
  • 2020-12-25
  • 2018-09-08
  • 1970-01-01
  • 2016-10-31
  • 1970-01-01
  • 2020-08-10
  • 2020-06-18
  • 2018-07-02
相关资源
最近更新 更多