泛型算法系列26:inplace_merge()

#include #include #include #include using namespace std; /************************************************************************/ /* */ template inline void my_inplace_merge(_BidIt _First, _BidIt _Mid, _BidIt _Last) { // merge [_First, _Mid) with [_Mid, _Last), using operator< if (_First != _Mid && _Mid != _Last) _Inplace_merge(_CHECKED_BASE(_First), _CHECKED_BASE(_Mid), _CHECKED_BASE(_Last), _Dist_type(_First), _Val_type(_First)); } template inline void _Inplace_merge(_BidIt _First, _BidIt _Mid, _BidIt _Last, _Diff *, _Ty *) { // merge [_First, _Mid) with [_Mid, _Last), using operator< _DEBUG_ORDER(_First, _Mid); _DEBUG_ORDER(_Mid, _Last); _Diff _Count1 = 0; _Distance(_First, _Mid, _Count1); _Diff _Count2 = 0; _Distance(_Mid, _Last, _Count2); _Temp_iterator<_Ty> _Tempbuf(_Count1 < _Count2 ? _Count1 : _Count2); my_Buffered_merge(_First, _Mid, _Last, _Count1, _Count2, _Tempbuf); } template inline void my_Buffered_merge(_BidIt _First, _BidIt _Mid, _BidIt _Last, _Diff _Count1, _Diff _Count2, _Temp_iterator<_Ty>& _Tempbuf) { // merge [_First, _Mid) with [_Mid, _Last), using operator< if (_Count1 + _Count2 == 2) { // order two one-element partitions if (_DEBUG_LT(*_Mid, *_First)) std::iter_swap(_First, _Mid); } else if (_Count1 <= _Count2 && _Count1 <= _Tempbuf._Maxlen()) { // buffer left partition, then merge _STDEXT unchecked_copy(_First, _Mid, _Tempbuf._Init()); _STDEXT unchecked_merge(_Tempbuf._First(), _Tempbuf._Last(), _Mid, _Last, _First); } else if (_Count2 <= _Tempbuf._Maxlen()) { // buffer right partition, then merge _STDEXT unchecked_copy(_Mid, _Last, _Tempbuf._Init()); _STDEXT _Unchecked_merge_backward(_First, _Mid, _Tempbuf._First(), _Tempbuf._Last(), _Last); } else { // buffer too small, divide and conquer _BidIt _Firstn, _Lastn; _Diff _Count1n, _Count2n; if (_Count2 < _Count1) { // left larger, cut it in half and partition right to match _Count1n = _Count1 / 2, _Count2n = 0; _Firstn = _First; std::advance(_Firstn, _Count1n); _Lastn = std::lower_bound(_Mid, _Last, *_Firstn); _Distance(_Mid, _Lastn, _Count2n); } else { // right larger, cut it in half and partition left to match _Count1n = 0, _Count2n = _Count2 / 2; _Lastn = _Mid; std::advance(_Lastn, _Count2n); _Firstn = std::upper_bound(_First, _Mid, *_Lastn); _Distance(_First, _Firstn, _Count1n); } _BidIt _Midn = _Buffered_rotate(_Firstn, _Mid, _Lastn, _Count1 - _Count1n, _Count2n, _Tempbuf); // rearrange middle my_Buffered_merge(_First, _Firstn, _Midn, _Count1n, _Count2n, _Tempbuf); // merge each new part my_Buffered_merge(_Midn, _Lastn, _Last, _Count1 - _Count1n, _Count2 - _Count2n, _Tempbuf); } } /************************************************************************/ template void print_elements( Type elem ) { cout << elem << " "; } /* * generates: ia sorted into two subarrays: 12 15 17 20 23 26 29 35 40 51 10 16 21 41 44 54 62 65 71 74 ia inplace_merge: 10 12 15 16 17 20 21 23 26 29 35 40 41 44 51 54 62 65 71 74 ivec sorted into two subvectors: 51 40 35 29 26 23 20 17 15 12 74 71 65 62 54 44 41 21 16 10 ivec inplace_merge: 74 71 65 62 54 51 44 41 40 35 29 26 23 21 20 17 16 15 12 10 */ int main() { int ia[] = { 29,23,20,17,15,26,51,12,35,40, 74,16,54,21,44,62,10,41,65,71 }; vector< int > ivec( ia, ia + 20 ); void (*pfi)( int ) = print_elements; // place the two subsequences in sorted order sort( &ia[0], &ia[10] ); sort( &ia[10], &ia[20] ); cout << "ia sorted into two sub-arrays: /n"; for_each( ia, ia+20, pfi ); cout << "/n/n"; inplace_merge( ia, ia + 10, ia + 20 ); cout << "ia inplace_merge:/n"; for_each( ia, ia + 20, pfi ); cout << "/n/n"; sort( ivec.begin(), ivec.begin() + 10, greater() ); sort( ivec.begin()+10, ivec.end(), greater() ); cout << "ivec sorted into two sub-vectors: /n"; for_each( ivec.begin(), ivec.end(), pfi ); cout << "/n/n"; inplace_merge( ivec.begin(), ivec.begin() + 10, ivec.end(), greater() ); cout << "ivec inplace_merge:/n"; for_each( ivec.begin(), ivec.end(), pfi ); cout << endl; return 0; }

你可能感兴趣的:(C++,STL,merge,算法,distance,iterator,class,each)