2014-12-06 2 views
11

std::inplace_merge 다음에 수행 할 알고리즘을 찾으려고 시도한 후 std::unique 할 것입니다. 2 패스보다 1 패스에서 더 효율적으로 보입니다. 표준 라이브러리 또는 oogling에서 찾을 수 없습니다.왜 std :: inplace_merge_unique가 없습니까?

  1. 그래서 어딘가에 다른 이름으로 부스트가 구현 되었습니까?
  2. 그런 알고리즘이 가능합니까 (일반적인 inplace_merge와 동일한 복잡성을 보장한다는 의미에서)?
+0

이러한 알고리즘은 구현하기가 쉽습니다. 병합 정렬의 병합 단계에서 요소를 쉽게 삭제할 수 있습니다. – kay

+0

부스트로 이것을 에뮬레이션하는 다소 해로운 방법은 Boost.Range 함수'boost :: inplace_merge'와'uniqued' 어댑터의 조합이 될 것입니다. 이는 범위가 반복되고 추가 N 단계를 추가하지 않는다는 점에서 '고유'지점을 지연시킵니다. 아직까지는 완벽하지 않습니다. – pmr

+0

pmr, 이것에 대해 확실합니까? 범위가 먼저 inplace_merged가되고 나면 독창적 인 것처럼 느껴 집니까? 컴파일러/부스트는 이들 2가 융합 될 수 있다는 것을 알지 못하기 때문에 – NoSenseEtAl

답변

4

미리 작동하지 않지만 범위가 중복되어 있지 않은 것으로 가정하면 std::set_union은 merge와 동일한 결과를 얻고 고유함을 찾습니다.

+0

이것은 옵션 중 하나입니다. 나는 고려했다. 그러나 그것은 틀린 장소 다. .. 내가 지금 발견했던 조용한 최고의 물건 그렇게 더하기 1 – NoSenseEtAl

4

알고리즘 섹션에는 많은 흥미로운 알고리즘이 없습니다. STL의 원래 제출은 Stepanov의 관점에서 불완전했으며 일부 알고리즘은 제거되었습니다. Alexander Stepanov와 Meng Lee의 proposal에는 알고리즘 inplace_merge_unique() 또는 그 변형이 포함되어 있지 않습니다.

이러한 알고리즘이없는 이유 중 하나는 요소를 삭제해야하는지 명확하지 않다는 것입니다. 비교는 엄격한 약한 순서이므로 요소의 선택이 중요합니다. 두 번째 범위에서 중복 모든 요소를 ​​제거하기 위해 사용 std::remove_if()

  1. inplace_merge_unique()을 구현하는 한 가지 방법이다.
  2. inplace_merge()을 사용하면 실제 병합을 수행 할 수 있습니다.

술어를 std::remove_if()으로 병합하면 병합 할 시퀀스의 첫 번째 부분의 현재 위치가 추적됩니다. 아래의 코드는 테스트되지 않았지만 그와 같은 것이 작동해야합니다.

template <typename BiDirIt, typename Comp> 
BiDirIt inplace_merge_unique(BiDirIt begin, BiDirIt middle, BiDirIt end, Comp comp) { 
    using reference = typename std::iterator_traits<BiDirIt>::reference; 
    BiDirIt result = std::remove_if(middle, end, [=](reference other) mutable -> bool { 
      begin = std::find_if(begin, middle, [=](reference arg)->bool { 
        return !comp(arg, other); 
       }); 
      return begin != middle && !comp(other, *begin); 
     }); 
    std::inplace_merge(begin, middle, result, comp); 
    return result; 
} 
관련 문제