2012-12-09 7 views
4

stable_sort에 복사 생성자가 필요한 이유는 무엇입니까? (swap이면 충분합니까?)
아니면 어떤 요소를 복사하지 않고 stable_sort 범위 내에서 어떻게해야합니까?복사하지 않고 stable_sort하는 방법은 무엇입니까?

#include <algorithm> 

class Person 
{ 
    Person(Person const &); // Disable copying 
public: 
    Person() : age(0) { } 
    int age; 
    void swap(Person &other) { using std::swap; swap(this->age, other.age); } 
    friend void swap(Person &a, Person &b) { a.swap(b); } 
    bool operator <(Person const &other) const { return this->age < other.age; } 
}; 

int main() 
{ 
    static size_t const n = 10; 
    Person people[n]; 
    std::stable_sort(people, people + n); 
} 
+0

내 머리 꼭대기에서 나는 본질적으로 * 스왑 * 작업을 기반으로하는 안정적인 정렬 알고리즘을 알지 못합니다. 그것들 모두는 * copy * 또는 더 정확하게, * move * operation을 기반으로하는 것으로 보입니다. 물론 스왑 *을 통해 * 이동 *을 에뮬레이션 할 수는 있지만 표준 라이브러리가 해당 구현 내에서 그렇게 할 것으로 기대하는 것은 이상 할 것입니다. – AnT

+0

@AndreyT : 사실, 저에게 또 다른 질문이 생깁니다 ... "왜 요소 자체가 아닌 대상을 기반으로 반복자를 정렬하지 않은 것입니까?" 하지만 지금은 (효율적인) 반복자를 사용하여 순위를 매기는 방법을 모릅니다 ... 따라서 새로운 질문입니다! 참조 : http://stackoverflow.com/questions/13791810/how-to-reorder-items-which-are-only-swapable – Mehrdad

+0

@AndreyT : 음, 어쩌면 나는 그 질문을 너무 빨리 요청했다. 재정렬에'sort'를 사용할 수 있습니다. 그런 다음 순위를 바꿀 수 있습니다. * 항목뿐입니다. 맞습니까? 그렇게하면 항목과 순위 사이의 일치를 유지하게되며 항목을 복사 할 필요가 없습니다. 제대로 작동해야합니까? 또는 나는 무엇인가 놓치고 있냐? – Mehrdad

답변

1

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>()); } 
+0

하하, 기본 구성 및 스와핑은 속임수입니다 ... 새로운 목표를 만드는 것을 피하는 방법에 어려움을 겪고있는 질문의 핵심을 피하고 있습니다! 하지만 좋은 시도. :) – Mehrdad

+0

@Mehrdad 표준 라이브러리 정렬을 사용하려는 경우 새 객체를 만드는 것을 피할 수 없습니다. (최소한 컨테이너 인덱스가 필요합니다.) 자신의 정렬 알고리즘을 기꺼이 사용하려면 2 가지 옵션이 있습니다. 버블 정렬과 같이 느리고 구현하기 쉬운 것 (2 줄의 코드로 작성할 수 있음) 또는 효율적이지만 복잡합니다. –

+0

죄송합니다. "새로운 객체"란 배열의 객체를 의미합니다. 명백히 인덱스는 괜찮습니다. 방금 형식이 스왑 및 액세스 가능한 생성자가없는 경우 작동해야한다는 것을 의미했습니다. – Mehrdad

1

나는 표준 사본을 소유하고 있지 않습니다.

25.4.1.2 stable_sort

[...]

이 필요합니다 : 먼저 스왑 요구 사항을 만족하여야한다 *의 유형 (그것은 가치가 무엇인지를 들어,이 무료로 사용할 수 2,010 초안의 표현입니다 표 37), MoveConstructible 요구 사항 (표 33) 및 MoveAssignable 요구 사항 (표 35).

최신 Visual C++로 테스트하면 이동 생성자가 정의되었지만 복사 생성자가 개인 일 때 정렬이 허용됩니다.

귀하의 질문에 대답하려면 : 당신은 운이 없어. std :: stable_sort 이외의 것을 사용하거나 래퍼 클래스를 사용하십시오.

+0

음, 괜찮아. 고마워. – Mehrdad

+0

C++ 표준위원회는 http://www.open-std.org/Jtc1/sc22/wg21/docs/papers/에있는 "C++ Working Draft"에 대한 업데이트를 정기적으로 발표합니다. 현재 가장 최근의 것 중 하나는 2012-11-02부터입니다. www.open-std.org/Jtc1/sc22/wg21/docs/papers/2012/n3485.pdf –

+0

@OlafDietsche 해당 링크를 가져 주셔서 감사합니다. –