Aka*_*tak 2 c++ sorting priority-queue c++11
我注意到std::priority_queue
以排序的方式存储元素。显然,以排序方式存储元素将是一个糟糕的设计选择,因为push
和的时间复杂度pop
将达到O(n)
。但事实证明,它std::priority_queue
神奇地在线性时间内对元素进行了排序。
这是我用于测试的代码。
#include <iostream>
#include <queue>
#include <algorithm>
#include <vector>
#include <chrono>
#include <random>
#include <climits>
#include <fstream>
#include <ios>
int main() {
int size = 10'000'000;
std::random_device rd;
std::mt19937 mt{rd()};
std::uniform_int_distribution<int> uid{1, INT32_MAX};
std::vector<int> vs;
for (int i = 0; i < size; ++i) {
vs.push_back(uid(mt));
}
// Measures time taken by make_heap
std::vector<int> vs1{vs};
auto start = std::chrono::system_clock::now();
std::make_heap(vs1.begin(), vs1.end());
auto end = std::chrono::system_clock::now();
std::chrono::duration<double> diff = end - start;
std::cout << "Time taken by make_heap: " << diff.count() << std::endl;
// Measures time taken by priority_queue
std::vector<int> vs2{vs};
start = std::chrono::system_clock::now();
std::priority_queue<int, std::vector<int>, std::greater<int>> qs{vs2.begin(), vs2.end()};
end = std::chrono::system_clock::now();
diff = end - start;
std::cout << "Time taken by priority_queue: " << diff.count() << std::endl;
// Measures time taken by sort
std::vector<int> vs3{vs};
start = std::chrono::system_clock::now();
std::sort(vs3.begin(), vs3.end());
end = std::chrono::system_clock::now();
diff = end - start;
std::cout << "Time taken by sort: " << diff.count() << std::endl;
std::ofstream ofile;
ofile.open("priority_queue_op.txt", std::ios::out);
for (int i = 0; i < size; ++i) {
ofile << qs.top() << std::endl;
qs.pop();
}
ofile.close();
ofile.open("sort_op.txt", std::ios::out);
for (auto& v : vs3)
ofile << v << std::endl;
ofile.close();
// run `diff priority_queue_op.txt sort_op.txt`
return 0;
}
Run Code Online (Sandbox Code Playgroud)
$ g++ -O3 test.cpp -o test
$ ./test
Time taken by make_heap: 0.133292
Time taken by priority_queue: 0.151002
Time taken by sort: 0.910701
$ diff priority_queue_op.txt sort_op.txt
$
Run Code Online (Sandbox Code Playgroud)
从上面的输出来看,似乎std::priority_queue
是在线性时间内对元素进行排序。
该站点建议std::priority_queue
使用标准库中的堆函数在内部管理堆。甚至源代码也证实了这一点。
$ g++ -O3 test.cpp -o test
$ ./test
Time taken by make_heap: 0.133292
Time taken by priority_queue: 0.151002
Time taken by sort: 0.910701
$ diff priority_queue_op.txt sort_op.txt
$
Run Code Online (Sandbox Code Playgroud)
插入过程用于插入元素,然后std::make_heap
构建堆。那么元素是如何神奇地排序的呢?即使有事情发生,它是如何在线性时间内发生的?
那么元素是如何神奇地排序的呢?
它们没有“排序”。
它们的排列方式使得应该位于“顶部”的元素位于正确的位置。其他元素不保证被排序。相反,它们被排列在所谓的堆中。
换句话说,astd::priority_queue
是一个经过优化的容器,可提供对逻辑上属于“顶部”的对象的快速访问,并假设其他元素只有在属于顶部时才会被访问。
“其他元素不会被访问”条件允许组织比完全排序更快。
即使有事情发生,它是如何在线性时间内发生的?
如果您指的是插入/删除,它实际上是在对数时间内完成的。
在对数时间内,保证前面的项位于正确的位置,同时保证所有其他项形成有效的堆。如果数据在插入/删除之前已经是堆,那么这不会花费很长时间。
归档时间: |
|
查看次数: |
237 次 |
最近记录: |