【问题标题】:Why is deque faster than queue?为什么双端队列比队列快?
【发布时间】:2020-04-19 21:44:53
【问题描述】:

我有以下工作代码(g++ 8.2,C++17 标准。)

    queue<TreeNode*> q{};

    q.push(root);
    q.push(nullptr);
    int sum = root -> val;
    while (!q.empty()) {
        TreeNode *n = q.front();
        q.pop();

        if (n != nullptr) {
            sum += n->val;
            if (n-> left != nullptr) q.push(n->left);
            if (n-> right != nullptr) q.push(n->right);   
        } else {
            if (q.empty()) break;
            q.push(nullptr);
            sum = 0;
        }

    }
    return sum;

然后我将queue&lt;TreeNode*&gt; 替换为deque&lt;TreeNode*&gt;。事实证明,速度至少提高了 20%。为什么deque&lt;TreeNode*&gt;queue&lt;TreeNode*&gt; 快那么多?

【问题讨论】:

  • 如果您指定用于此发现的编译器会很有帮助
  • 您是在测试未优化的调试版本还是优化的发布版本?你的编译器标志/选项是什么?
  • 您能否提供用于进行计时的最少代码以及用于编译代码的编译器设置?

标签: c++ data-structures queue deque


【解决方案1】:

来自cppreference.com: std::queue

template<
    class T,
    class Container = std::deque<T>
> class queue;

Container - 用于存储元素的底层容器的类型。

所以std::queue - 默认情况下 - 使用 std::deque 作为其内部容器,因为它最多只能与 std::deque(或一般的底层容器)一样快,并且因为它是一个包装器是 - 取决于编译器可以做的优化 - 较慢。因此,如果您正确测量了 20% 的减速,那么您就可以衡量编译器在给定优化级别优化包装器代码的能力。

由于 std::queue 的存在是为了保证 FIFO 的使用,因此我怀疑仅公开这些函数——但我现在无法对其进行测试——开启优化后速度会急剧下降。如果是这样,我会认为这是编译器或库实现功能的错误/缺陷。

【讨论】: