【问题标题】:How does std::priority_queue accomplish O(log n) insertion? [duplicate]std::priority_queue 如何完成 O(log n) 插入? [复制]
【发布时间】:2021-12-08 18:40:39
【问题描述】:

documentation for std::priority_queuepush 操作的复杂性表述为:

比较的对数加上Container::push_back的复杂度。

并且默认使用std::vector 作为底层容器。但是,push_back 只能将元素推送到向量的末尾,而在优先级队列中,可能需要在向量中间的某个位置添加元素,在这种情况下,必须将后面的所有元素都向右移动。在最坏的情况下,在开始添加元素时,推送操作将产生全部 O(n) 成本。那么优先级队列是如何在对数时间内做到的呢?为什么它默认使用向量而不是诸如堆之类的“简单插入和查找”容器?

【问题讨论】:

    标签: c++ time-complexity priority-queue


    【解决方案1】:

    在优先级队列中,可能需要在向量中间的某处添加元素,在这种情况下,后面的所有元素都必须向右移动

    没有。不会发生右移。

    新元素被添加到末尾,索引i:O(1)

    然后将其优先级与索引 i/2 处的父级进行比较,如果优先级更高则交换。

    如果发生交换,比较下一个

    重复以上 2 个步骤,直到到达索引 0。 O(log(i))

    【讨论】:

    • @WaisKamal 是的,它是数组中的最后一个元素,但不是优先级的最后一个元素。该数组按优先级顺序保存项目。 array[0] 最高,array[1]array[2] 次之,均低于array[0]
    • @WaisKamal 二叉堆不是完全有序的集合。请查看here 以了解它们的工作原理。你所做的假设是完全错误的。
    • @WaisKamal 你需要摆脱排序列表的心态。它不是那样工作的。如果是这样,记录在案的行为将是不可能的,并且数据结构将与已排序的向量无法区分......并且没有多大用处。
    • @WaisKamal 请记住,在index = 0 删除/报告最高优先级项目需要 O(1),然后在 index * 2 + 1index * 2 + 2 检查其子项以找到哪个向上移动,然后重复寻找孩子的替代品,依此类推。所有这些都是 O(log(n)) 的工作。
    • @WaisKamal 我建议您发布 可编译 代码,用于“每当我将元素添加到队列并打印它包含的元素”以及为什么得出“元素总是排序”作为关于“为什么”的新问题。发布使用的准确输入、看到的输出、预期的输出是一个很好的问题。提示:一个一个地访问优先级队列元素是否每次都花费 O(1) 类时间?
    猜你喜欢
    • 2011-12-12
    • 2012-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-09
    • 2021-09-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多