equality (1) template <class ForwardIterator1, class ForwardIterator2> bool is_permutation (ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2); predicate (2) template <class ForwardIterator1, class ForwardIterator2, class BinaryPredicate> bool is_permutation (ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, BinaryPredicate pred);
功能:
判断区间[ first1 , last1 )是否是以first2为开始的区间的一个排列,如果是,返回真。
例子:
// is_permutation example #include <iostream> // std::cout #include <algorithm> // std::is_permutation #include <array> // std::array int main () { std::array<int,5> foo = {1,2,3,4,5}; std::array<int,5> bar = {3,1,4,5,2}; if ( std::is_permutation (foo.begin(), foo.end(), bar.begin()) ) std::cout << "foo and bar contain the same elements.\n"; return 0; }运行如下:foo and bar contain the same elements.
二:源码剖析 不得不说这完全可以作为一个笔试面试算法题,源码给出的解答也相当巧妙,值得学习。
源码有点长,记得从底往上读!!!
// TEMPLATE FUNCTION next template<class _FwdIt> inline _FwdIt next(_FwdIt _First, typename iterator_traits<_FwdIt>::difference_type _Off = 1) { // increment iterator static_assert(is_base_of<forward_iterator_tag, typename iterator_traits<_FwdIt>::iterator_category>::value, "next requires forward iterator"); _STD advance(_First, _Off); return (_First); } // TEMPLATE FUNCTION _Count_pr WITH PRED template<class _InIt, class _Ty, class _Pr> inline typename iterator_traits<_InIt>::difference_type _Count_pr(_InIt _First, _InIt _Last, const _Ty& _Val, _Pr _Pred) { // count elements that match _Val, using _Pred typename iterator_traits<_InIt>::difference_type _Count = 0; for (; _First != _Last; ++_First) if (_Pred(*_First, _Val)) ++_Count; return (_Count); } // TEMPLATE FUNCTION _Find_pr WITH PRED template<class _InIt, class _Ty, class _Pr> inline _InIt _Find_pr(_InIt _First, _InIt _Last, const _Ty& _Val, _Pr _Pred) { // find first matching _Val, using _Pred for (; _First != _Last; ++_First) if (_Pred(*_First, _Val)) break; return (_First); } // TEMPLATE FUNCTION _Trim_matching_suffixes WITH PRED template<class _FwdIt1, class _FwdIt2, class _Pr> inline void _Trim_matching_suffixes(_FwdIt1&, _FwdIt2&, _Pr, forward_iterator_tag, forward_iterator_tag) { // trim matching suffixes, forward iterators (do nothing) } template<class _FwdIt1, class _FwdIt2, class _Pr> inline void _Trim_matching_suffixes(_FwdIt1& _Last1, _FwdIt2& _Last2, _Pr _Pred, bidirectional_iterator_tag, bidirectional_iterator_tag) { // trim matching suffixes, bidirectional iterators // assumptions: same lengths, non-empty, !_Pred(*_First1, *_First2) while (_Pred(*--_Last1, *--_Last2)) ; // find last inequality ++_Last1; ++_Last2; } // TEMPLATE FUNCTION _Check_match_counts WITH PRED template<class _FwdIt1, class _FwdIt2, class _Pr> inline bool _Check_match_counts(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _FwdIt2 _Last2, _Pr _Pred) { // test if [_First1, _Last1) == permuted [_First2, _Last2), using _Pred, same lengths _Trim_matching_suffixes(_Last1, _Last2, _Pred,//从尾往前查看区间是否满足pred,即查看它们的后缀,具体函数在上面 _Iter_cat(_Last1), _Iter_cat(_Last2)); typedef typename iterator_traits<_FwdIt1>::difference_type _Diff1; typedef typename iterator_traits<_FwdIt2>::difference_type _Diff2; for (_FwdIt1 _Next1 = _First1; _Next1 != _Last1; ++_Next1) if (_Next1 == _Find_pr(_First1, _Next1, *_Next1, _Pred)) { // new value, compare match counts _Diff2 _Count2 = _Count_pr(_First2, _Last2, *_Next1, _Pred); if (_Count2 == 0) return (false); // second range lacks value, fail _FwdIt1 _Skip1 = _STD next(_Next1); _Diff1 _Count1 = _Count_pr(_Skip1, _Last1, *_Next1, _Pred) + 1; if (_Count2 != _Count1) return (false); // match counts differ, fail } return (true); } // TEMPLATE FUNCTION is_permutation WITH PRED template<class _FwdIt1, class _FwdIt2, class _Pr> inline bool _Is_permutation(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _Pr _Pred) { // test if [_First1, _Last1) == permuted [_First2, ...), using _Pred for (; _First1 != _Last1; ++_First1, (void)++_First2) if (!_Pred(*_First1, *_First2)) { // found first inequality, check match counts in suffix _FwdIt2 _Last2 = _STD next(_First2,//必须要保证比较的两个区间长度,后者一定比前者长,或者相等 _STD distance(_First1, _Last1)); return (_Check_match_counts(_First1, _Last1,//实际的源码的判断在上面_Check_match_counts() _First2, _Last2, _Pred)); } return (true); } #if _ITERATOR_DEBUG_LEVEL == 0 template<class _FwdIt1, class _FwdIt2, class _Pr> inline bool is_permutation(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _Pr _Pred) { // test if [_First1, _Last1) == permuted [_First2, ...), using _Pred return (_Is_permutation(_Unchecked(_First1), _Unchecked(_Last1), _Unchecked(_First2), _Pred)); } #else /* _ITERATOR_DEBUG_LEVEL == 0 */ template<class _FwdIt1, class _FwdIt2, class _Pr> inline bool _Is_permutation2(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _Pr _Pred, true_type) { // test if [_First1, _Last1) == permuted [_First2, ...), // using _Pred, checked input return (_Is_permutation(_First1, _Last1, _First2, _Pred)); } template<class _FwdIt1, class _FwdIt2, class _Pr> inline _SCL_INSECURE_DEPRECATE bool _Is_permutation2(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _Pr _Pred, false_type) { // test if [_First1, _Last1) == permuted [_First2, ...), // using _Pred, unchecked input return (_Is_permutation(_First1, _Last1, _First2, _Pred)); } template<class _FwdIt1, class _FwdIt2, class _Pr> inline bool is_permutation(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2, _Pr _Pred) { // test if [_First1, _Last1) == permuted [_First2, ...), using _Pred _DEBUG_RANGE_PTR(_First1, _Last1, _First2); _DEBUG_POINTER_IF(_First1 != _Last1, _Pred); return (_Is_permutation2(_Unchecked(_First1), _Unchecked(_Last1), _First2, _Pred, _Is_checked(_First2))); } #if _ITERATOR_DEBUG_ARRAY_OVERLOADS template<class _FwdIt1, class _InTy, size_t _InSize, class _Pr> inline bool is_permutation(_FwdIt1 _First1, _FwdIt1 _Last1, _InTy (&_First2)[_InSize], _Pr _Pred) { // test if [_First1, _Last1) == permuted [_First2, ...), using _Pred return (_STD is_permutation(_First1, _Last1, _Array_iterator<_InTy, _InSize>(_First2), _Pred)); } #endif /* _ITERATOR_DEBUG_ARRAY_OVERLOADS */ #endif /* _ITERATOR_DEBUG_LEVEL == 0 */ // TEMPLATE FUNCTION is_permutation template<class _FwdIt1, class _FwdIt2> inline bool is_permutation(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2) { // test if [_First1, _Last1) == permuted [_First2, ...) return (_STD is_permutation(_First1, _Last1, _First2, equal_to<>())); } #if _ITERATOR_DEBUG_ARRAY_OVERLOADS template<class _FwdIt1, class _InTy, size_t _InSize> inline bool is_permutation(_FwdIt1 _First1, _FwdIt1 _Last1, _InTy (&_First2)[_InSize]) { // test if [_First1, _Last1) == permuted [_First2, ...) return (_STD is_permutation(_First1, _Last1, _First2, equal_to<>())); } #endif /* _ITERATOR_DEBUG_ARRAY_OVERLOADS */
源码摘抄自Visual Studio 2015安装目录algorithm文件中。
点击进入目录----> C++源码剖析目录