Python 3:在O(1)时间内从基于节点的Deque的前端和末端弹出

时间:2017-09-30 16:40:05

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

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

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

我试图让我的Deque类在O(1)时间从两端出队,但我的问题是下一个指针只朝一个方向发展。通过设置我创建的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
            # ??????
            # ??????

2 个答案:

答案 0 :(得分:2)

您需要一个双重链接列表才能在O(1)中实现您的目标。

您可以继承Node class并添加指向上一个节点的指针,并在Deque class中使用它。

或者,正如评论中所指出的,你可以使用两个单链表(第二个链接相反),但这看起来不太实用。

答案 1 :(得分:2)

在评论中指出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类中定义。{/ p>