【问题标题】:Sorting bidimensional arrays by column using STL使用 STL 按列对二维数组进行排序
【发布时间】:2017-03-31 19:32:57
【问题描述】:

this 问题中,我们看到了如何通过每个向量的第一个元素对向量进行排序的很好的解释,以及通过每个向量并按其元素排序的第二个示例。

我知道对于 STL 的高级用户而言,数组不是 C++ 的一等公民,但我喜欢数组(就像 Andrei Alexandrescu)。

所以,让我们考虑一下代码:

typedef int arr2D[3];

arr2D array2D[3] = { { 1, 4, 3 },
                     { 9, 2, 5 },
                     { 7, 6, 8 } };

std::sort(begin(array2D[2]), end(array2D[2]), greater<>());

这样的结果是,将array2D的最后按降序排列,如下所示:

1 4 3
9 2 5
8 7 6 <- last row by descending order

但是,我想要的是按降序排列 array2D 的最后 ,如下所示:

1 4 8
9 2 5
7 6 3
    ^
    └--- last column by descending order

使用普通的arrays(不是向量)和std::sort,有人可以帮我吗?

谢谢

【问题讨论】:

  • 很遗憾,您不能使用std::sort 对“列”进行排序。您可以将它们提取到单独的数组(或向量)中(因此 newArray[0] 对应于 array2D[0][2] 等),对其进行排序,然后将排序后的值写回您的数组中。
  • 您必须在排序之前和之后转置矩阵。
  • 一些程序员老兄和乔纳斯:我和你们两个想法一样,但是在我阅读你的cmets之前,我认为我错了。现在我确信std :: sort 只能应用于连续的数据结构。

标签: c++ sorting c++11 multidimensional-array


【解决方案1】:

您可以编写一个自定义迭代器,在每一行上迭代特定列中的元素。像这样的:

template<class Arr>
using sub_array_t = std::remove_pointer_t<std::decay_t<Arr>>;

template<class Arr>
using column_iterator_base = std::iterator<std::random_access_iterator_tag, sub_array_t<sub_array_t<Arr>>>;

template<std::size_t col_index, class Arr>
struct column_iterator : column_iterator_base<Arr>
{
    using parent = column_iterator_base<Arr>;
    using value_type = typename parent::value_type;
    using difference_type = typename parent::difference_type;
    using sub_array = sub_array_t<Arr>;

    Arr* arr;
    sub_array* row;

    column_iterator(Arr* arr)                 : arr(arr), row(*arr) {}
    column_iterator(Arr* arr, sub_array* row) : arr(arr), row(row) {}

    column_iterator begin() {return {arr};}
    column_iterator end()   {return {arr, std::end(*arr)};}

    column_iterator& operator+=(difference_type rhs) {row += rhs; return *this;}
    column_iterator& operator-=(difference_type rhs) {row -= rhs; return *this;}
    value_type& operator*() const {return (*row)[col_index];}
    value_type* operator->() const {return (*row) + col_index;}
    value_type& operator[](difference_type rhs) const {return row[rhs][col_index];}

    column_iterator& operator++() {++row; return *this;}
    column_iterator& operator--() {--row; return *this;}
    column_iterator operator++(int) {column_iterator tmp(arr, row); ++row; return tmp;}
    column_iterator operator--(int) {column_iterator tmp(arr, row); --row; return tmp;}

    difference_type operator-(const column_iterator& rhs) const {return row-rhs.row;}
    column_iterator operator+(difference_type rhs) const {return column_iterator(arr, row+rhs);}
    column_iterator operator-(difference_type rhs) const {return column_iterator(arr, row-rhs);}
    friend inline column_iterator operator+(difference_type lhs, const column_iterator& rhs)
    {return column_iterator(rhs.arr, lhs+rhs.row);}
    friend inline column_iterator operator-(difference_type lhs, const column_iterator& rhs)
    {return column_iterator(rhs.arr, lhs-rhs.row);}

    bool operator==(const column_iterator& rhs) const {return row == rhs.row;}
    bool operator!=(const column_iterator& rhs) const {return row != rhs.row;}
    bool operator> (const column_iterator& rhs) const {return row >  rhs.row;}
    bool operator< (const column_iterator& rhs) const {return row <  rhs.row;}
    bool operator>=(const column_iterator& rhs) const {return row >= rhs.row;}
    bool operator<=(const column_iterator& rhs) const {return row <= rhs.row;}
};

template<std::size_t col_index, class Arr>
auto make_column_iterator(Arr* arr)
{
    return column_iterator<col_index, Arr>(arr);
}


int main()
{
    // array2D = ...
    auto foo = make_column_iterator<1>(&array2D);
    std::sort(foo.begin(), foo.end());
}

使用 boost 中的某些东西可能可以避免自定义迭代器的许多样板。

注意:这写得很快,可能包含错误和不必要的复杂代码。

【讨论】:

  • 感谢您的努力,但正如您所说,它存在我无法纠正的错误。
  • @user7140484 它的行为与您预期的不一样吗?
  • 代码甚至无法编译,我无法理解错误。
  • @user7140484 您需要包含使用的标准标头。您需要添加定义array2D 的代码。另外,我刚刚注意到您已经标记了问题 c++11。此代码使用了一些 c++14 功能(std::remove_pointer_tstd::decay_tauto 返回类型),因此如果您的编译器不支持当前标准,则需要将这些功能移植到 c++11。
  • 哦,这可能是一些错误的原因,因为一个错误正是关于 auto return type 。编译器说error C3551: expected a trailing return type,我什至不知道std::remove_pointer_tstd::decay_t 是什么意思。如果您可以重写代码的 C++11 版本,我将标记为已接受的答案(如果有效)。
猜你喜欢
  • 1970-01-01
  • 2013-08-17
  • 2013-12-16
  • 2016-05-09
  • 2021-02-03
  • 1970-01-01
  • 1970-01-01
  • 2018-06-02
  • 1970-01-01
相关资源
最近更新 更多