Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/161.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用stl排序就地排序表_C++_Algorithm_Sorting_Stl - Fatal编程技术网

C++ 使用stl排序就地排序表

C++ 使用stl排序就地排序表,c++,algorithm,sorting,stl,C++,Algorithm,Sorting,Stl,我有一个(I,j,k)格式的巨大表(大约50Gb)(来自稀疏矩阵)存储为 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)对这些条目进行排序不幸的是,很难说

我有一个(I,j,k)格式的巨大表(大约50Gb)(来自稀疏矩阵)存储为

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)对这些条目进行排序不幸的是,很难说服
std::sort
,或任何标准库使用条带化数据。其设计目的是假设数据可以通过单个
=
进行复制,通过一个
移动
进行移动,或通过一个
交换
进行交换

最好的方法是使用
boost::iterator\u facade
编写一个自定义迭代器类来包装数据,并从
std::sort
中隐藏条带化数据格式。我过去也想做类似的事情,但我的工作区不允许我们使用
boost
编辑:当您的外观被取消引用时,它可能需要创建某种代理对象,该对象可以被分配/移动/交换,并对每个条带阵列执行正确的操作。这不是小事


下一个最好的选择是将
int
s从0到N组成一个数组,每个数组代表条带化数据数组中的一个索引。编写一个自定义函子到
std::sort
,该函子对该数组进行排序以符合您的条件。当您拥有如此大的数据集时,这显然远远不够理想。

如果您必须继续使用现有的数据结构,它本质上是三个
std::vector
tuple
,那么使用
boost::zip\u迭代器似乎是一种可行的方法。
zip_迭代器
将三个迭代器(两个用于索引,一个用于值)视为一个元组,您可以使用自定义比较函数对象对数据进行就地排序。唉,
boost::zip_迭代器
不能与
std::sort
一起使用,如中所述,因为它不能写入

这意味着您必须编写自己的zip_迭代器类,该类可以与
std::sort
一起使用。请注意,这不是一个简单的练习,请参见和/或此


std::tuple
std::vector
进行排序要容易得多。下面我尝试使用两个索引和一个值的
std::tuple
,并将这些条目存储到
std::vector
中。对于排序,我使用一个C++14通用lambda,它将两个索引转发到一个较小的元组中,并使用库
运算符按字典顺序(即,首先在行索引上,然后在列索引上)比较这些索引。简言之,请查看
std::sort
的3参数版本,然后查找
函子
函数对象
。因此您需要提供帮助--如果我给您两个(I,j,k)值,那么告诉我们如何确定第一个值是否在第二个值之前。这张桌子是什么形状的?您需要更详细地告诉我们这些数据是如何构造的。那么您想对所有三个数组进行排序吗?最简单的方法是将它们组合成一个
struct
,只需要一个该类型的数组,我不知道如何使用sort的三参数版本。随机访问迭代器在这里是什么?这就是我关于非标准数据类型的意思:如果您的值按照Jonathan的建议存储为单个类对象,那么可以使用示例来处理此类问题(这对我来说是不可行的,因为构建这样的结构作为数据的第二个副本会耗尽内存),但是,如果你的数据分布在多个数组中,没有什么问题。我认为这个答案最接近你想要的,但是你可能想考虑为真正巨大的数组优化你自己的排序。50 GB的数据,即使RAM中的数据通过外部排序算法得到更好的处理,以更好地利用访问的局部性;这也是一个公平的赌注,你也将受益于并行排序。好的观点。我的回答是“你能在这里使用
std::sort
”而不是“你应该”。我上面列出的所有技巧可能比复制粘贴一个基本的
qsort
实现并调整它以满足您的需要更费劲,手动调整的实现也可能更快。取消引用时返回代理的迭代器不是RandomAccessIterator,因为ForwardIterator取消引用时,需要返回
value\u-type&
const-value\u-type&
。(根据[forward.iterators]/1.3)
std::tie
std::forward_as_tuple
键入速度快一点,在这种情况下也有相同的效果。@Casey
std::tie
只接受左值,而
std::forward_as_tuple
也适用于按值返回的getter。另外,
std::tie
不是
constepr>,因此我养成了不使用
std::tie
的习惯。没有按值返回的
std::get
重载,而且几乎不可能扩展,因为(a)禁止在
std
中重载函数,以及(b)部分专门化函数是不可能的。当传递左值时,这样的扩展按值返回也是相当不合理的。在任何情况下,我确实编辑了我的注释,添加了“在这个实例中”;@Casey更新了我的答案,tnx!顺便说一句,使用getter,您可以编写类似于
std::tie(L.row(),L.column())
的内容,而不是
std::get
,当然是这样。我把你评论中的“getters”误认为是
std::get
的味道。现在这更有意义了。
(i1 < i2) || (i1==i2 && j1 <= j2)
#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";
}