使用 STL 排序对表进行排序
sorting table in place using stl sort
我有一个巨大的表(大约50Gb(,格式为(i,j,k((来自稀疏矩阵(,存储为
uint32_t * idx1, * idx2;
float * vals;
uint32_t tablesize;
我想使用给定的比较函数对其进行排序,该函数是 idx1 和 idx2 的函数。这可以使用std::sort来完成吗?
具体来说,稀疏矩阵中每个值为 v 的非零条目 (i,j( 通过将 i 放在 idx1 中,j 放在 idx2 中,v 放在 vals 中的相应条目中来存储。然后我想根据 (i1, j1, v1( 对这些条目进行排序 <= (i2, j2, v2( 如果
(i1 < i2) || (i1==i2 && j1 <= j2)
我能够搜索到在非标准数据类型上使用std::sort的示例假设要比较的每个项目都是一个类的单个实例;在这里,每个项目都由不同数组中的三个值表示。
不幸的是,很难说服std::sort
或任何标准库使用条带化数据。它旨在假设数据可以通过单个=
复制,通过一个move
移动或通过一个swap
交换。
最好的办法是使用 boost::iterator_facade
编写一个自定义迭代器类,该类包装数据,并对std::sort
隐藏条带化数据格式。我过去想做类似的事情,但我的工作空间不允许我们使用boost
。编辑:当您的外观被取消引用时,它可能需要创建某种可以分配/移动/交换的代理对象,并对每个条带数组执行正确的操作。这不是小事。
下一个最好的选择是制作一个从 0 到 N 的 int
数组,每个数组代表条带化数据数组中的一个索引。编写一个自定义函子来std::sort
该函子对此数组进行排序以符合您的条件。当你有这么大的数据集时,这显然远非理想。
如果您必须继续使用现有的数据结构(本质上是三个std::vector
的std::tuple
(,那么使用boost::zip_iterator
似乎是要走的路。zip_iterator
将三个迭代器(两个到索引,一个到一个值(视为单个元组,您可以使用自定义比较函数对象就地对数据进行排序。唉,boost::zip_iterator
不能与std::sort
一起使用,正如本问答中所解释的那样,因为它不能被写入。
这意味着您必须编写自己的 zip_iterator 类,该类可以与 std::sort
一起使用。请注意,这不是一个微不足道的练习,请参阅此问答和/或本文。
对std::tuple
的std::vector
进行排序要容易得多。我在下面的尝试使用两个索引和一个值的std::tuple
,并将这些条目存储到一个std::vector
中。对于排序,我使用 C++14 通用 lambda 将两个索引转发到一个较小的元组中,并使用 std::tuple
的库operator<
按字典顺序比较它们(即首先在行索引上,然后在列索引上
#include <algorithm>
#include <iostream>
#include <tuple>
#include <vector>
using index = uint32_t;
using value = float;
using sparse_entry = std::tuple<index, index, value>;
using sparse_matrix = std::vector<sparse_entry>;
int main()
{
// sparse 3x3 matrix
auto m = sparse_matrix {
std::make_tuple( 1, 1, -2.2),
std::make_tuple( 1, 0, 42 ),
std::make_tuple( 0, 2, 3.4),
std::make_tuple( 0, 1, 1.7)
};
// sort by row-index, then column-index
std::sort(begin(m), end(m), [](auto const& L, auto const& R) {
return
std::forward_as_tuple(std::get<0>(L), std::get<1>(L)) <
std::forward_as_tuple(std::get<0>(R), std::get<1>(R))
;
});
for (auto const& elem : m)
std::cout << "{ " << std::get<0>(elem) << ", " << std::get<1>(elem) << ", " << std::get<2>(elem) << "}, n";
}
活生生的例子。
如果您的应用程序可以使用这种转换后的数据布局(并且可能存在缓存性能原因导致它不能(,那么上面的代码将根据需要进行排序。
注意:正如@Casey提到的,您也可以使用 std::tie
而不是 std::forward_as_tuple
,但是当您将 sparse_entry
更改为一个成熟的用户定义类并返回 getter 按值时,这可能会咬您。
- 使用2个键的cpp-stl::优先级队列排序不正确
- 在STL - C++中按成绩对学生列表进行排序?
- C++ STL 排序会检查 NaN 吗?
- 使用列表 STL 递归进行插入排序
- 如何使用 STL 排序对具有模板专用化的自定义类对象进行排序?
- 使用STL对用户输入数组进行排序的错误有什么解决方案吗?
- 如何根据对的第二个元素对 STL c++ 中的一组对进行排序?
- C++ wrt 字符串中的 STL 排序函数
- 如何检查队列是否使用 STL 排序
- STL按客户"<"运算符对向量进行排序。为什么要将"<"运算符定义为 const?
- C :STL STL阵列的STL排序
- STL 排序,保留原始顺序
- 列表STL的时间复杂性在一段时间内进行排序
- 为 STL 列表编写选择排序
- c ++ 是否有 STL 算法来检查范围是否严格排序
- 对 STL 容器进行排序
- 使用 stl::map 和 stl::unordered_map 对包含大量重复元素的数组数据进行排序
- 使用另一个stl向量重新排序stl向量
- 在两个值上排序STL向量
- 排序STL列表的子类