【问题标题】:How to destroy a queue efficiently?如何有效地销毁队列?
【发布时间】:2017-04-21 07:56:29
【问题描述】:

我实现了自己的队列数据结构。我使用单向链表实现了队列。它是在类定义中实现的。链表的头指向队列的前端,链表的尾指向队列的尾。请注意,我保留尾部只是为了在 O(1) 时间内完成推送操作。

现在类的 push 函数为一个值动态分配内存,然后将其推送到列表的末尾。并且pop函数释放分配给前面的值的内存。

当队列被破坏(超出范围)时,我想释放分配的内存,所以我为队列编写了一个析构函数。我的析构函数遍历整个链表并删除链表的每个元素。时间复杂度为 O(n)。有什么办法可以降低队列的时间复杂度?是否可以在 O(1) 中销毁队列?如果我只释放了链表的头,链表的其余元素不会被删除,并且由于头被删除,链表的其他元素将无法删除。 STL队列的析构函数是如何实现的?它会在 O(1) 或 O(n) 中破坏整个队列吗?

my_queue 的析构函数代码如下:

/*
Node is a struct which is the nodes of the linked list.
It has two attributes: val(of type char) and next(of type node*)
*/
my_queue :: ~my_queue(){
    node * temp;
    while(head != NULL){
        temp = head;
        head = head->next;
        delete temp;
    }
    sz = 0;
    tail = NULL;
}

【问题讨论】:

  • 如果你使用链表,我认为 O(N) 是你能得到的最好的。如果您通过类似于std::vector 的方式实现它,您可以获得 O(1) 的推送和弹出摊销以及 O(1) 的免费。
  • @Winestone 对于任何非平凡的 value_type,向量破坏将是 O(N)。如果你有 n 个对象,你需要 n 次调用析构函数。
  • @juanchopanza 你说得对,我假设有int 的队列。
  • 可以在O(1)中清除vector吗?
  • 我认为它需要像一个免费电话一样长,这需要像this很多时间

标签: c++ c++11 memory-management linked-list queue


【解决方案1】:

是否可以在 O(1) 中销毁队列?

如果您打算继续使用链表,则不会。 O(n) 是破坏链表(或任何基于节点的数据结构)的最佳渐近复杂度。

如果您使用非平凡的析构函数存储对象,也不会。您不能在恒定时间内调用 N 个析构函数。

如果您选择另一种数据结构来实现您的队列,那么也许可以。一个动态增长的数组(即一个向量)可以在恒定时间内被销毁,如果元素是可以轻易破坏的。

STL队列的析构函数是如何实现的?它会在 O(1) 或 O(n) 中破坏整个队列吗?

std::queue 只是较低级别容器的包装器。它的析构函数只是破坏你选择的底层容器。复杂性是该容器的析构函数的复杂性。 O(n) 对于具有非平凡析构函数的任何对象容器,对于所有 std::dequestd::list,对于具有平凡析构函数的 std::vector 元素的 O(1)。

在这里,复杂性是根据对free 的调用或任何释放内存的方法来描述的。 free 本身的复杂性可能无法保证保持不变。

【讨论】:

    猜你喜欢
    • 2019-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-01
    • 1970-01-01
    • 2019-08-21
    • 2019-09-27
    相关资源
    最近更新 更多