使用自定义比较功能对静态多维数组进行排序
Sorting static multi dimentional array with custom compare function
有一些对向量进行排序或动态分配数组的例子,但我找不到任何关于静态数组的帮助。假设我有一个数组
int array[10][10];
和一个比较函数,
bool compare(const int (*a)[10], const int (*b)[10]);
当我这样称呼它时,
std::sort(array, array + 10, compare);
我有编译错误:error: cannot convert 'int*' to 'const int (*)[10]' in argument passing
我尝试了很多方法,在排序函数中将数组转换为(void**)
,但随后我遇到了分段错误。我的问题是使用数组作为函数参数,但我无法弄清楚如何使用这个 std::sort。否则,我将不得不编写自己的排序函数。
类型为 T
的元素容器上调用 std::sort
时,比较函数需要接收类型 T
或 const T&
的参数。在这种情况下,您有一个二维数组,因此元素的类型是一维数组int[10]
。由于一维数组衰减为指针,因此compare
可以是:
bool compare(int a[10], int b[10]);
或等效:
bool compare(int *a, int *b);
这将修复您遇到的错误,但您的代码仍然不起作用:std::sort
需要容器元素可分配(或在 C++11 中可移动),但数组不可分配。
您可以按照人们的建议改用std::vector<std::vector<int> >
。请注意,您对性能问题的恐惧是错误的:即使可以对二维数组进行排序,也会涉及大量一维数组的复制,这将需要很长时间。另一方面,交换向量是通过简单地交换指针来完成的,这更快。通常,如果您没有先测试过性能,则不应对性能做出假设。
比较函数不会获得传递给元素的迭代器,而是获取取消引用的迭代器,即值类型。因此,您的比较函数需要声明如下:
bool compare(int (&a0)[10], int (&a1)[10]);
您可以验证是否确实可以使用数组迭代器调用它:
compare(*(std::begin(array) + 0), *(std::begin(array) + 1));
但是,这无法对数组进行排序:内置数组不可复制分配。对静态大小的数组(其中外部维度灵活)进行排序的最简单方法是使用 std::array<T, N>
:
std::array<int, 10> array[10];
std::sort(std::begin(array), std::end(array));
我说,如果我们要使用STL并C++..让我们用现代风格编写它并真正使用STL。
我尝试使用现代 c++11 解决问题:
#include <vector>
#include <iostream>
#include <algorithm>
typedef std::vector<int> ArrayInt;
typedef std::vector< std::vector<int> > ArrayData;
bool compare(const ArrayInt& a, const ArrayInt& b) {
std::cout << &(a) << ' ' << &(b) << std::endl;
int sumA = std::accumulate(a.begin(), a.end(), 0);
int sumB = std::accumulate(b.begin(), b.end(), 0);
return sumA < sumB;
}
int main(int argc, char** argv) {
ArrayData array = {
{1,2,4,0,3,7,6,8,3,3},
{13,2,4,0,3,7,6,8,3,3},
{10,2,4,0,3,7,6,8,3,3},
{1,2,4,0,3,7,6,8,3,3},
{16,2,4,0,3,7,6,8,3,3},
{1,2,400,0,3,7,6,8,3,3},
{1,2,4,0,3,7,6,8,3,3},
{120,2,4,0,3,7,6,8,3,3},
{1,2,4,0,3,7,6,8,3,3},
{1,2,4,0,3,7,6,8,3,3}
};
std::sort(array.begin(), array.end(), compare);
for (auto row : array) {
for (int num : row)
std::cout << num << ' ';
std::cout << std::endl;
}
}
它使用累加对每个子数组求和,并对总和进行排序......效率非常低,因为它必须多次对同一行求和......但它只是为了炫耀自定义比较函数。
作为练习,我编写了这个版本,它使用异步将求和部分分布在任何可用内核上,以便在排序之前进行求和。很抱歉有点跑题了。我希望它对某些人仍然有用:
#include <vector>
#include <iostream>
#include <algorithm>
#include <future>
typedef std::vector<int> IntRow;
typedef std::pair<int, IntRow> DataRow;
typedef std::vector<DataRow> DataTable;
int main(int argc, char** argv) {
// Holds the sum of each row, plus the data itself
DataTable array = {
{0, {1,2,4,0,3,7,6,8,3,3}},
{0, {13,2,4,0,3,7,6,8,3,3}},
{0, {10,2,4,0,3,7,6,8,3,3}},
{0, {1,2,4,0,3,7,6,8,3,3}},
{0, {16,2,4,0,3,7,6,8,3,3}},
{0, {1,2,400,0,3,7,6,8,3,3}},
{0, {1,2,4,0,3,7,6,8,3,3}},
{0, {120,2,4,0,3,7,6,8,3,3}},
{0, {1,2,4,0,3,7,6,8,3,3}},
{0, {1,2,4,0,3,7,6,8,3,3}}
};
// Make use of multiple cores if it's efficient enough
// get the sum of each data row
std::vector<std::future<int>> sums(array.size());
auto next = sums.begin();
for (auto& row : array)
*next++ = std::async([](const IntRow& row) { return std::accumulate(row.begin(), row.end(), 0); }, row.second);
// Get the results
auto nextRow = array.begin();
for (auto& sum: sums)
(*nextRow++).first = sum.get();
// Sort it
std::sort(array.begin(), array.end(),
[](const DataRow& a, const DataRow& b) { return a.first < b.first; });
// Print it
for (auto row : array) {
for (int num : row.second)
std::cout << num << ' ';
std::cout << std::endl;
}
}
它需要使用 pthread 库或类似的东西进行编译:
g++ -O6 sort.cpp --std=c++11 -g -lpthread
- 显示错误输出的简单数组排序程序
- C 使用单个函数对具有多种值类型的数组排序
- 2D数组排序,空格打乱顺序
- C 2D数组排序
- C++数组排序 - 将"bbba"和"0001"视为不正确排序的问题
- 数组排序功能
- CString 数组排序
- 简单的数组排序/检查 划分和征服版本
- C++ 中的多维数组排序
- 选择在++中对并行数组排序
- C++:二维指针数组排序:选择排序不适用于某些实例
- C++字符串数组排序
- C++中的指针数组排序算法
- 在VC++6中使用向量进行数组排序时出错,而在VC++2012中没有错误
- 将索引数组排序为主数组
- 数组排序、数组输入、数组输出
- C++数组排序,内存错误
- 在嵌入式系统上将数组排序功能从c++移植到c
- 基于其他int数组排序
- 多维数组排序c++奇怪行为