根据某一行对整个 2D 向量进行排序

sort entire 2d vector on the basis of a certain row

本文关键字:2D 向量 排序 一行      更新时间:2023-10-16

我有兴趣在第二行的基础上对整个二维向量进行排序。我尝试了一些仅对第二行进行排序的代码,但是,我希望它适用于整个 2d 向量。

#include<iostream>
#include<vector> 
#include<algorithm> 
int main()
{
    std::vector< std::vector<int> > vect{{3, 5, 1},
                                         {4, 8, 6},
                                         {7, 2, 9}};
    int m = vect.size();
    int n = vect[0].size();
    sort(vect[1].begin(), vect[1].end());
    std::cout << "After sorting :n";
    for (int i=0; i<m; i++)
    {
        for (int j=0; j<n ;j++)
            std::cout << vect[i][j] << " ";
        std::cout << std::endl;
    }
    return 0;
}

输出如下:

3 5 1 
4 6 8 
7 2 9 

但我希望它是

3 1 5
4 6 8
7 9 2
创建一个转置向量的函数,因此它应该将 {{3, 5, 1}, {4, 8, 6}, {7, 2, 9}}

修改为 {{3,4,7},{5,8,2},{1,6,9}}。使用函数转置向量,然后使用自定义比较器对向量进行排序,比较行的第二个元素。然后再次调用转置函数。

转置函数可能看起来像

std::vector< std::vector<int> > transpose(std::vector< std::vector<int> >& vect)
{
 std::vector< std::vector<int> > transposed(vect[0].size(), std::vector<int>());
 for (size_t i = 0; i < vect.size(); ++i)
  for (size_t j = 0; j < vect[0].size(); ++j)
    transposed[j].push_back(vect[i][j]);
 return transposed;
}

然后整个代码将是

vect = transpose(vect);                                     
std::sort(vect.begin(), vect.end(), 
  [](const std::vector<int>& lhs, const std::vector<int>& rhs)
     {return lhs[1] < rhs[1];});                                     
vect = transpose(vect);                                     

如果向量是正方形的,那么可以就地进行换位,使解决方案比一般解决方案更有效。

问题的结构不允许我们使用内置的排序函数。因为,自定义排序只会提供"行"。而且您只能比较"行"。

但是有一些替代方法可以实现这一点。

例如,您可以通过转置矢量的向量来做到这一点。

"转置>按列排序>转置"可能会解决您的问题。

但我的解决方案是基于另一种动态。

  1. 对第 n 列进行排序并将索引保留为数组。(n 是有序行的位置)
  2. 使用步骤 1 中定义的数组,逐个对所有行进行排序。

http://cpp.sh/4dkzg

#include<iostream>
#include<vector> 
#include<algorithm> 
using namespace std;
template <typename T>
vector<size_t> sort_indexes(const vector<T> &v) {
  // initialize original index locations
  vector<size_t> idx(v.size());
  iota(idx.begin(), idx.end(), 0);
  // sort indexes based on comparing values in v
  sort(idx.begin(), idx.end(),
       [&v](size_t i1, size_t i2) {return v[i1] < v[i2];});
  return idx;
}
int main()
{
    std::vector< std::vector<int> > vect{{3, 5, 1, 2},
                                         {4, 8, 6, 1},
                                         {7, 2, 9, 5}};
    int m = vect.size();
    int n = vect[0].size();
    int sortByRow = 1; // starts from 0, if 1 => order by using 2nd row.
    /* generate reference for our actual sort operation */
    std::vector<size_t> indexSort = sort_indexes(vect[sortByRow]);
    /* sort each row using our reference vector */
    for (int i=0; i<m; i++)
    {      
        int temp[n];
        for (int j=0; j<n; j++)
            temp[j] = vect[i][indexSort[j]];
        // Copy back temp[] to vector
        for (int j=0; j<n; j++)
            vect[i][j]  = temp[j];
    }
    std::cout << "After sorting :n";
    for (int i=0; i<m; i++)
    {
        for (int j=0; j<n ;j++)
            std::cout << vect[i][j] << " ";
        std::cout << std::endl;
    }
    return 0;
}

http://www.geeksforgeeks.org/reorder-a-array-according-to-given-indexes/(如果要应用就地排序,有一些修复)

您可以进行std::pair<int,int>std::vector,其中在向量的第 i 个元素的第一个变量中,您有第二行的第 i 个值,而在第二个变量中,您有索引 i 的值。

然后,根据对的第一个值对该向量进行排序。这样,您可以创建一个新的 2D 向量,在该向量中,您可以在每一行中根据元素对的第二个值(即旧索引)对元素进行排序。

std::vector< std::vector<int> > vect{{ 3, 5, 1 },{ 4, 8, 6 },{ 7, 2, 9 }};
std::vector<std::pair<int, int>> row;
for (int i = 0; i < vect[1].size(); ++i){
    row.push_back({vect[1][i],i});
}
sort(row.begin(), row.end());
std::vector< std::vector<int> > sorted;
std::vector<int> sortedRow;
for (int i = 0; i < vect.size(); ++i){
    for (int j = 0; j < vect[i].size(); ++j){
        sortedRow.push_back(vect[i][row[j].second]);
    }
    sorted.push_back(sortedRow);
    sortedRow.clear();
}

你必须#include <utility>.

这段代码很脏。 但与您想要的代码完全相同。

#include<iostream>
#include<vector>
#include<algorithm>
std::vector< std::vector<int> > vect = { {3, 5, 1}, {4, 8, 6}, {7, 2, 9} };
int findInVector(std::vector<int> input, int temp)
{
    for(int i=0;i<input.size();i++)
    {
        if(input[i] == temp)
        {
            return i;
        }
    }
}
bool myfunction (int i,int j)
{
    bool ret;
    if(i<j)
    {
        int i_pos = findInVector( vect[1], i);
        int j_pos = findInVector( vect[1], j);
        int temp  = vect[0][i_pos];
        vect[0][i_pos] = vect[0][j_pos];
        vect[0][j_pos] = temp;
        temp  = vect[2][i_pos];
        vect[2][i_pos] = vect[2][j_pos];
        vect[2][j_pos] = temp;
        ret = true;
    }
    else
    {
        ret = false;
    }
    return ret;
}
int main()
{
    int m = vect.size();
    int n = vect[0].size();
    sort(vect[1].begin(), vect[1].end(), myfunction);
    std::cout << "After sorting :n";
    for (int i=0; i<m; i++)
    {
        for (int j=0; j<n ;j++)
            std::cout << vect[i][j] << " ";
        std::cout << std::endl;
    }
    return 0;
}