使用 std::sort 对具有特定标准的二维向量进行排序

Posted

技术标签:

【中文标题】使用 std::sort 对具有特定标准的二维向量进行排序【英文标题】:Sorting a 2D vector with specific criteria using std::sort 【发布时间】:2017-04-16 21:24:35 【问题描述】:

我遇到了一个关于使用库algorithm 中的std::sort 对二维向量(矩阵)进行排序的编码问题

例如,假设我有一个 2D 向量

1,8,3
1,9,1
1,4,2 
    ^

我想按第 3 列对其进行排序(例如增长标准) 所以排序后我想要一个矩阵:

1,9,1
1,4,2
1,8,3
    ^

我知道要在std::sort 中指定排序条件,需要在std::sort 中发送第三个函数。如果它是一维vector,那将不是问题。我会在 std::sort 内创建一个带有 2 个参数的 lambda,比较它们并返回 true/false。

所以现在您可以看到我面临的问题,我如何访问矩阵中的特定元素,在我的例子中是第三列元素并将它们与std::sort 进行比较?

#include <iostream>
#include <vector>
#include <algorithm>

void printMatrix(std::vector<std::vector<int>> m) 
    for(int i = 0; i < m.size(); i++) 
        for(int j = 0; j < m[i].size(); j++) 
            std::cout << m[i][j] << " ";
        
        std::cout << std::endl;
    


int main() 
    std::vector<std::vector<int>> m
        1,8,3,
        1,9,1,
        1,4,2
    ;

    std::sort(m.begin(), m.end(), [](int a, int b)  // error
                // ???
    );
    printMatrix(m);

    return 0;

我不想使用任何其他外部库来解决这个问题。

非常感谢任何帮助! :)

【问题讨论】:

【参考方案1】:
std::sort(m.begin(), m.end(), [](int a, int b)  // error
                // ???
    );

m.begin()m.end() 返回的迭代器中的value_typestd::vector&lt;int&gt;。因此,您的 lambda 需要为其两个参数采用该 type

std::sort(m.begin(), m.end(), 
        [](const std::vector<int>& a, const std::vector<int>& b) 
               return a.at(2) < b.at(2);
    );

注意:我在这里使用at() 成员函数而不是运算符[] 来防止UB,如果您错误地尝试在无效索引中进行排序。

Demo

【讨论】:

谢谢!解决方案比我想象的要简单! :) @galaxyworks。不客气。随时!我很高兴这解决了你的问题。 :-)【参考方案2】:

当您要对std::vector&lt;std::vector&lt;int&gt;&gt; 进行排序时,容器的项目类型为std::vector&lt;int&gt;,而不是int。因此,您不能在声明中使用lambda

[](int a, int b)  ... 

对这样的容器进行排序。您需要在声明中使用lambda

[](std::vector<int> a, std::vector<int> b)  ... 

[](std::vector<int> const& a, std::vector<int> const& b)  ... 

使用第一个版本的成本很高,因为每次调用lambda 都会复制std::vector。因此,建议使用第二个版本。

std::sort(m.begin(), m.end(), [](std::vector<int> const& a,
                                 std::vector<int> const& b) 
   return a.back() < b.back();
);

【讨论】:

【参考方案3】:

虽然不是最有效的解决方案,但最简单的做法是转置您的 2D 向量(也称为矩阵),对每个向量进行排序,然后再次转置。这是一个经过测试的工作函数,可以为您执行此操作:

template<typename T>
void sortColumns(vector<vector<T> > &v)
    vector<vector<T> > rv(v[0].size(), vector<T>(v.size()));
    for(int i = 0; i < v.size(); i++)
        for(int j = 0; j < v[i].size(); j++)
            rv[j][i] = v[i][j];
        
    
    for(int i = 0; i < rv.size(); i++)
        sort(rv[i].begin(), rv[i].end());
        for(int j = 0; j < rv[i].size(); j++)
            v[j][i] = rv[i][j];
        
    

同样,这不是按列对矩阵进行排序的最有效或最现代的方法,但它有效且易于理解。

【讨论】:

以上是关于使用 std::sort 对具有特定标准的二维向量进行排序的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 std::sort() 对指向值的向量进行排序?

C++ - 使用 std::sort 对结构向量进行排序导致读取访问冲突

使用 std::sort() 对对象向量进行排序

如何使用单独类的属性对向量进行 std::sort [关闭]

使用 std::sort 对包含两个数据成员的对象向量进行排序

对空向量进行 std::sort [关闭]