使用自定义比较函数对静态多维数组进行排序

时间:2012-12-17 23:40:57

标签: c++ stl sorting

有一些排序向量或动态分配的数组的例子,但我找不到有关静态数组的任何帮助。假设我有一个数组

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。否则,我将不得不编写自己的排序函数。

3 个答案:

答案 0 :(得分:2)

在类型为std::sort的元素的容器上调用T时,比较函数需要接收Tconst T&类型的参数。在这种情况下,您有一个二维数组,因此元素的类型是一维数组int[10]。由于1维数组衰减为指针,compare可以是:

bool compare(int a[10], int b[10]);

或等效地:

bool compare(int *a, int *b);

这将修复你得到的错误,但是你的代码仍然不能工作:std::sort需要容器元素可以分配(或在C ++ 11中移动),但是数组不可分配。

您可以根据人们的建议使用std::vector<std::vector<int> >。请注意,您对性能问题的恐惧是错误的:即使可能对二维数组进行排序,也会涉及大量复制一维数组,这需要很长时间。另一方面,交换向量是通过简单地交换更快的指针来完成的。一般而言,如果您尚未先测试,则不应对性能做出假设。

答案 1 :(得分:1)

我说,如果我们要使用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;
    }
}

它使用accumulate对每个子数组求和,并对总和进行排序..它的效率非常低,因为它必须多次对同一行求和。但它只是用来展示自定义比较函数。


作为练习,我编写了这个版本,它使用async在任何可用的内核上分配求和部分,以便在排序之前进行求和。对不起它有点偏离主题。我希望它对某些人有用:

#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

答案 2 :(得分:1)

比较函数不会获得传递的元素的迭代器,而是取消引用的迭代器,即值类型。因此,您的比较函数需要声明如下:

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));