OP 토론에서 확장하고 흥미로운 점을 발견했기 때문에 인덱스 래퍼를 사용하여 원본 벡터를 정렬하기 위해 스왑을 사용하는 솔루션이 있습니다.
편집 : 이것은 솔루션 v2에서 바뀌어 있습니다.
편집 (OP 기준) : C++을 필요로하지 않는 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>()); }
내 머리 꼭대기에서 나는 본질적으로 * 스왑 * 작업을 기반으로하는 안정적인 정렬 알고리즘을 알지 못합니다. 그것들 모두는 * copy * 또는 더 정확하게, * move * operation을 기반으로하는 것으로 보입니다. 물론 스왑 *을 통해 * 이동 *을 에뮬레이션 할 수는 있지만 표준 라이브러리가 해당 구현 내에서 그렇게 할 것으로 기대하는 것은 이상 할 것입니다. – AnT
@AndreyT : 사실, 저에게 또 다른 질문이 생깁니다 ... "왜 요소 자체가 아닌 대상을 기반으로 반복자를 정렬하지 않은 것입니까?" 하지만 지금은 (효율적인) 반복자를 사용하여 순위를 매기는 방법을 모릅니다 ... 따라서 새로운 질문입니다! 참조 : http://stackoverflow.com/questions/13791810/how-to-reorder-items-which-are-only-swapable – Mehrdad
@AndreyT : 음, 어쩌면 나는 그 질문을 너무 빨리 요청했다. 재정렬에'sort'를 사용할 수 있습니다. 그런 다음 순위를 바꿀 수 있습니다. * 항목뿐입니다. 맞습니까? 그렇게하면 항목과 순위 사이의 일치를 유지하게되며 항목을 복사 할 필요가 없습니다. 제대로 작동해야합니까? 또는 나는 무엇인가 놓치고 있냐? – Mehrdad