В дополнение к обсуждению в ОП и потому, что мне это показалось интересным, вот решение, которое использует только обмен для сортировки исходного вектора (с использованием оболочки указателя для сортировки индексов).
Редактировать: это решение v2, которое заменяется на месте.
Редактировать (от OP): версия для STL, для которой не требуется С++ 11.
template<class Pred>
struct swapping_stable_sort_pred
{
Pred pred;
swapping_stable_sort_pred(Pred const &pred) : pred(pred) { }
template<class It>
bool operator()(
std::pair<It, typename std::iterator_traits<It>::difference_type> const &a,
std::pair<It, typename std::iterator_traits<It>::difference_type> const &b) const
{
bool less = this->pred(*a.first, *b.first);
if (!less)
{
bool const greater = this->pred(*b.first, *a.first);
if (!greater) { less = a.second < b.second; }
}
return less;
}
};
template<class It, class Pred>
void swapping_stable_sort(It const begin, It const end, Pred const pred)
{
typedef std::pair<It, typename std::iterator_traits<It>::difference_type> Pair;
std::vector<Pair> vp;
vp.reserve(static_cast<size_t>(std::distance(begin, end)));
for (It it = begin; it != end; ++it)
{ vp.push_back(std::make_pair(it, std::distance(begin, it))); }
std::sort(vp.begin(), vp.end(), swapping_stable_sort_pred<Pred>(pred));
std::vector<Pair *> vip(vp.size());
for (size_t i = 0; i < vp.size(); i++)
{ vip[static_cast<size_t>(vp[i].second)] = &vp[i]; }
for (size_t i = 0; i + 1 < vp.size(); i++)
{
typename std::iterator_traits<It>::difference_type &j = vp[i].second;
using std::swap;
swap(*(begin + static_cast<ptrdiff_t>(i)), *(begin + j));
swap(j, vip[i]->second);
swap(vip[j], vip[vip[j]->second]);
}
}
template<class It>
void swapping_stable_sort(It const begin, It const end)
{ return swapping_stable_sort(begin, end, std::less<typename std::iterator_traits<It>::value_type>()); }
person
Andrei Tita
schedule
10.12.2012
sort
для изменения порядка, а затем поменять местами и элементы, верно? Таким образом, вы сохраните соответствие между элементами и рейтингом, и вам никогда не придется копировать элементы... это должно работать нормально? Или я что-то упускаю? - person user541686   schedule 10.12.2012std::sort
-инг этого массива вместо этого всегда являются простым и жизнеспособным подходом к выполнению стабильной сортировки (массива индексов). В дополнение к вашим критериям сравнения (например, сравнениеage
выше) вы также должны сравнить значения итератора, которые стабилизируют сортировку. Однако, чтобы переупорядочить исходный массив в соответствии с вашим отсортированным индексом (если вам это действительно нужно), вам все равно потребуется операция move. - person AnT   schedule 10.12.2012