您的位置:首页 > 其它

泛型算法系列13:equal_range()

2009-08-13 17:29 405 查看
#include <algorithm>
#include <vector>
#include <utility>
#include <iostream>
#include<functional>
using namespace std;

/* generates:
array element sequence after sort:
12 15 17 19 20 22 23 26 29 35 40 51

equal_range result of search for value 23:
*ia_iter.first: 23         *ia_iter.second: 26

equal_range result of search for absent value 21:
*ia_iter.first: 22         *ia_iter.second: 22

vector element sequence after sort:
51 40 35 29 26 23 22 20 19 17 15 12

equal_range result of search for value 26:
*ivec_iter.first: 26       *ivec_iter.second: 23

equal_range result of search for absent value 21:
*ivec_iter.first: 20       *ivec_iter.second: 20
*/
/************************************************************************/
/*                                                                      */
template<class _InIt, class _Diff> inline
void __CLRCALL_OR_CDECL my_Advance(_InIt& _Where, _Diff _Off)
{	// increment iterator by offset, input iterators
for (; 0 < _Off; --_Off)
++_Where;
}
/************************************************************************/

template<class _FwdIt, class _Ty> inline
pair<_FwdIt, _FwdIt> my_equal_range(_FwdIt _First, _FwdIt _Last, const _Ty& _Val)
{	// find range equivalent to _Val, using operator<
return (my_Equal_range(_First, _Last, _Val, _Dist_type(_First)));
}

template<class _FwdIt, class _Ty, class _Diff> inline
pair<_FwdIt, _FwdIt> my_Equal_range(_FwdIt _First, _FwdIt _Last,
const _Ty& _Val, _Diff *)
{	// find range equivalent to _Val, using operator<
_DEBUG_ORDER_SINGLE(_First, _Last, true);
_Diff _Count = 0;
_Distance(_First, _Last, _Count);

for (; 0 < _Count; )
{	// divide and conquer, check midpoint
_Diff _Count2 = _Count / 2;
_FwdIt _Mid = _First;
std::advance(_Mid, _Count2);
_DEBUG_ORDER_SINGLE(_Mid, _Last, false);

if (_DEBUG_LT(*_Mid, _Val))
{	// range begins above _Mid, loop
_First = ++_Mid;
_Count -= _Count2 + 1;
}
else if (_Val < *_Mid)
_Count = _Count2;	// range in first half, loop
else
{	// range straddles mid, find each end and return
_FwdIt _First2 = lower_bound(_First, _Mid, _Val);
std::advance(_First, _Count);
_FwdIt _Last2 = upper_bound(++_Mid, _First, _Val);
return (pair<_FwdIt, _FwdIt>(_First2, _Last2));
}
}

return (pair<_FwdIt, _FwdIt>(_First, _First));	// empty range
}

int main()
{
int ia[] = { 29,23,20,22,17,15,26,51,19,12,35,40 };
vector< int > ivec( ia, ia+12 );
ostream_iterator< int > ofile( cout, " " );

sort( &ia[0], &ia[12] );
cout << "array element sequence after sort:/n";
copy( ia, ia+12, ofile ); cout << "/n/n";

pair< int*,int* > ia_iter;
ia_iter = my_equal_range( &ia[0], &ia[12], 23 );

cout << "equal_range result of search for value 23:/n/t"
<< "*ia_iter.first: "     << *ia_iter.first << "/t"
<< "*ia_iter.second: " << *ia_iter.second << "/n/n";

ia_iter = equal_range( &ia[0], &ia[12], 21 );

cout << "equal_range result of search for "
<< "absent value 21:/n/t"
<< "*ia_iter.first: "     << *ia_iter.first << "/t"
<< "*ia_iter.second: " << *ia_iter.second << "/n/n";

sort( ivec.begin(), ivec.end(), greater<int>() );

cout << "vector element sequence after sort:/n";
copy( ivec.begin(), ivec.end(), ofile ); cout << "/n/n";

typedef vector< int>::iterator iter_ivec;
pair< iter_ivec, iter_ivec > ivec_iter;

ivec_iter = equal_range( ivec.begin(), ivec.end(), 26,
greater<int>() );

cout << "equal_range result of search for value 26:/n/t"
<< "*ivec_iter.first: "     << *ivec_iter.first << "/t"
<< "*ivec_iter.second: " << *ivec_iter.second
;

ivec_iter = equal_range( ivec.begin(), ivec.end(), 21,
greater<int>() );

cout << "equal_range result of search for "
<< "absent value 21:/n/t"
<< "*ivec_iter.first: "     << *ivec_iter.first << "/t"
<< "*ivec_iter.second: " << *ivec_iter.second
;

return 0;
}

/************************************************************************/
/*                                                                      */
template<class _Ty, class _Elem = char, class _Traits = char_traits<_Elem> >
class ostream_iterator : public _Outit
{	// wrap _Ty inserts to output stream as output iterator
public:
typedef _Elem char_type;
typedef _Traits traits_type;
typedef basic_ostream<_Elem, _Traits> ostream_type;

#if _SECURE_SCL
typedef _Range_checked_iterator_tag _Checked_iterator_category;
#endif

ostream_iterator(ostream_type& _Ostr,
const _Elem *_Delim = 0)
: _Myostr(&_Ostr), _Mydelim(_Delim)
{	// construct from output stream and delimiter
}

ostream_iterator<_Ty, _Elem, _Traits>& operator=(const _Ty& _Val)
{	// insert value into output stream, followed by delimiter
*_Myostr << _Val;
if (_Mydelim != 0)
*_Myostr << _Mydelim;
return (*this);
}

ostream_iterator<_Ty, _Elem, _Traits>& operator*()
{	// pretend to return designated value
return (*this);
}

ostream_iterator<_Ty, _Elem, _Traits>& operator++()
{	// pretend to preincrement
return (*this);
}

ostream_iterator<_Ty, _Elem, _Traits> operator++(int)
{	// pretend to postincrement
return (*this);
}

protected:
static void _Xran()
{	// report an out_of_range error
_THROW(out_of_range, "invalid ostream_iterator");
}

const _Elem *_Mydelim;	// pointer to delimiter string (NB: not freed)
ostream_type *_Myostr;	// pointer to output stream
};
/************************************************************************/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: