在我目前的任务中,我需要从数据库中读取大约10,000条记录(学生数据)并需要将其存储在容器中。现在我需要选择容器来存储所有这些记录以生成报告。报告生成选项是供应商特定的,因为一个供应商想要转储所有记录而不进行排序,而其他供应商希望根据排序的名称字段生成报告。我从我的结尾选择了矢量,因为我不需要在中间插入任何类型,并且第一个选项不需要搜索工作(报告没有排序字段)但是对于第二个选项可以任何人建议我,如果矢量是合适的选项通过引入基于名称字段的排序来实现相同目的。
下面是我在第23项中的scott meyers book(Effective STL)中找到的一些有用的指示。我相信基于以下信息,第二个选项需要使用排序的向量,但我仍然希望有人在得出任何结论并开始编码之前通过一些指示。
项目23.考虑用已排序的向量替换关联容器
“**标准关联容器通常实现为平衡二叉搜索树。平衡二叉搜索树是针对插入,删除和查找的混合组合进行优化的数据结构。也就是说,它是专为应用程序设计的做一些插入,然后一些查找,然后可能一些更多的插入,然后可能一些擦除,然后一些更多的查找,然后更多的插入或删除,然后更多的查找等。这一系列事件的关键特征是插入,删除和查找都混淆了。一般来说,没有办法预测树上的下一个操作是什么“
答案 0 :(得分:0)
正如Scott Meyers所说,std::vector
是一个非常好的容器,用于存储数据并操纵它 - 除了一些例外 - 如果数据非常大 - 不仅仅是元素数量而且元素大小都很重要。
您可以通过不操纵数据本身来减少要操作的数据大小 - 但是通过操纵索引来处理该数据。
假设你已经从文件中读取了矢量:
struct Element { .... };
std::vector<Element> data;
readData(someFile);
您可以通过创建这样的索引向量来生成这些记录的“自然顺序”(参见iota on cppreference):
using indices = std::vector<std::size_t>;
indices naturalOrder(data.size());
std::iota(naturalOrder.begin(), naturalOrder.end(), 0); // filled with 0,1,2,...
使用此索引打印记录 - 定义此类算法:
template <typename Container, typename Indices, typename Operation>
void for_erach(Container&& container, const Indices& indices, Operation&& op)
{
for (auto i: indices)
op(container[i]);
}
// print in natural order
for_each(data, naturalOrder, [] (auto const& e) {
std::cout << e << std::endl;
});
要排序,只需对索引进行排序:
Indices sorterdByXOrder = naturalOrder;
auto lessX = [&data](auto i, auto j) { return data[i].x < data[j].x; };
std::sort(sorterdByXOrder.begin(), sorterdByXOrder.end(), lessX);
// print in sorted by x order
std::cout << "Sorted by x:" << std::endl;
for_each(data, sorterdByXOrder , [] (auto const& e) {
std::cout << e << std::endl;
});
仅包含例如索引element.y == 7 - 执行此操作:
Indices onlyY7Order;
auto yIs7 = [&data](auto i) { return data[i].y == 7; };
std::copy_if(naturalOrder.begin(), naturalOrder.end(),
std::back_inserter(onlyY7Order), yIs7);
如果您要将整个数据读取到std::vector
会遇到性能问题 - 您可以尝试使用std::deque
- 在某些情况下可能会更快。我提供的其余代码不会更改 - 因为std::deque
和std::vector
具有非常相似的接口...