Я использую метод, объясненный здесь. Как получить перестановку индекса после сортировки, чтобы найти перестановку индекса, которая сортирует элементы массива.
Как ни странно, в некоторых случаях я получаю ошибки сегментации. Отслеживая проблему, я обнаружил, что std::sort
пытается вызвать компаратор с индексами за пределами допустимого диапазона. Я уверен, что всегда перед вызовом std::sort
массив index
заполняется правильными индексами (например, 0
to data.size()-1
).
Интересно отметить, что в моем случае data
всегда имеют длину 32
и я понимаю, что компаратор вызывается с первым аргументом 145
(а второй всегда является чем-то в диапазоне от 0
до 31
).
Любая идея, почему это может произойти?
Вот код:
class compare {
private:
const double* list;
public:
compare(const double* d): list(d) {}
bool operator()(const size_t& a, const size_t& b) {
// indeed I observe that this function gets called with a = 145 and b in
// the range of 0 to 31
return (list[a] < list[b]);
}
};
std::vector<double> data(32);
std::vector<size_t> idx(32);
compare cmp(&data[0]);
size_t i;
// populate the data array ... for example:
for (i = 0; i < 32; i++)
data[i] = 1.0 * (rand() % 100) / 50;
for (i = 0; i < 32; i++)
idx[i] = i;
std::sort(idx.begin(), idx.end(), cmp);
Я не могу воспроизвести то, что вы наблюдаете. Вот очищенная версия вашего кода, которая, кажется, работает нормально (gcc и clang).
#include <vector>
#include <algorithm>
#include <stdexcept>
#include <cstdlib>
#include <cstdio>
#define LSIZE 32
// ------------------------------------------------------------------------
class compare
{
private:
const double* ptr;
public:
compare(): ptr(0) {}
compare( const double* d ): ptr(d) {}
bool operator()( size_t a, size_t b )
{
if ( ptr == 0 ) throw std::runtime_error("Null pointer to data.");
if ( a >= LSIZE || b >= LSIZE ) throw std::out_of_range("Index out of range.");
// Uncomment to show the comparisons:
// printf( "Comparing data[%lu] (%.2f) and data[%lu] (%.2f)\n",
// a, ptr[a], b, ptr[b] );
return ptr[a] < ptr[b];
}
};
// ------------------------------------------------------------------------
int main()
{
std::vector<double> data(LSIZE);
std::vector<size_t> idx(LSIZE);
for ( unsigned i=0; i<LSIZE; ++i )
{
idx[i] = i;
data[i] = 1.0 * (rand() % 100) / 50;
}
std::sort( idx.begin(), idx.end(), compare( data.data() ) );
}