你发现有sort和stable_sort,还有 partition 和stable_partition, 感到奇怪吧。其中的区别是,带有stable的函数可保证相等元素的原本相对次序在排序后保持不变。或许你会问,既然相等,你还管他相对位置呢,也分不清 楚谁是谁了?这里需要弄清楚一个问题,这里的相等,是指你提供的函数表示两个元素相等,并不一定是一摸一样的元素。
例如,如果你写一个比较函数:
bool less_len(const string &str1, const string &str2) { return str1.length() < str2.length(); }
此时,"apple" 和 "winter" 就是相等的,如果在"apple" 出现在"winter"前面,用带stable的函数排序后,他们的次序一定不变,如果你使用的是不带"stable"的函数排序,那么排序完 后,"Winter"有可能在"apple"的前面。
这个应用在数组里面不受影响,当函数参数传入的是结构体时,会发现两者之间的明显区别。
Partition:将满足条件的元素向前移动.
// TEMPLATE FUNCTION partition
template class _Pr> inline _BidIt _Partition(_BidIt _First, _BidIt _Last, _Pr _Pred) { // move elements satisfying _Pred to beginning of sequence for (; ; ++_First)//最外层循环是一次往后面找元素 { // find any out-of-order pair for (; _First != _Last && _Pred(*_First); ++_First)//找到使得_Pred为false的元素 ; // skip in-place elements at beginning if (_First == _Last) break; // done for (; _First != --_Last && !_Pred(*_Last); )//找到是的_Pred为true的元素. ; // skip in-place elements at end if (_First == _Last) break; // done _STD iter_swap(_First, _Last); // swap out-of-place pair and loop //经过两个内循环的查找,前者是的_Pred为false,后者使得_Pred为true的元素已经找到,并交换彼此 } return (_First); } 需要注意的一点:vs2010的stl实现方式中,很喜欢使用if( -- iter )/for(_First != --_Last)这类的表达式,这类表达式的有点是代码量少,程序整洁,但是缺点就是容易造成语义判断错误,比如--iter中,即使if判断失败iter也减一操作. Stable_partition:将满足条件的元素向前移动.(但不改变初始状态的相对顺序) // TEMPLATE FUNCTION stable_partition template class _Pr, class _Diff, class _Ty> inline _BidIt _Stable_partition(_BidIt _First, _BidIt _Last, _Pr _Pred, _Diff _Count, _Temp_iterator<_Ty>& _Tempbuf) { // partition preserving order of equivalents, using _Pred if (_Count == 0) return (_First); else if (_Count == 1) return (_Pred(*_First) ? _Last : _First); else if (_Count <= _Tempbuf._Maxlen()) { // temp buffer big enough, copy right partition out and back _BidIt _Next = _First; for (_Tempbuf._Init(); _First != _Last; ++_First) if (_Pred(*_First)) *_Next++ = _Move(*_First); else *_Tempbuf++ = _Move(*_First); _Move(_Tempbuf._First(), _Tempbuf._Last(), _Next); // copy back return (_Next); } else { // temp buffer not big enough, divide and conquer _BidIt _Mid = _First; _STD advance(_Mid, _Count / 2); _BidIt _Left = _Stable_partition(_First, _Mid, _Pred, _Count / 2, _Tempbuf); // form L1R1 in left half _BidIt _Right = _Stable_partition(_Mid, _Last, _Pred, _Count - _Count / 2, _Tempbuf); // form L2R2 in right half _Diff _Count1 = 0; _Distance(_Left, _Mid, _Count1); _Diff _Count2 = 0; _Distance(_Mid, _Right, _Count2); return (_Buffered_rotate(_Left, _Mid, _Right, _Count1, _Count2, _Tempbuf)); // rotate L1R1L2R2 to L1L2R1R2 } } 这里涉及到另外一个类:_Temp_iterator,有涉及到_Move这个函数. _Move没有看懂.想看看源码剖析,结果发现里面并没有找到这个函数的实现方式.再一次对源码剖析感到失望. _Temp_iterator这个类不知道实际功能是做什么. 暂时就过这个函数. 举例: int main() { vector for ( int i = 1;i <= 9;++ i ) { vecInt.push_back( i ); } partition( vecInt.begin(),vecInt.end(),bind2nd( modulus copy( vecInt.begin(),vecInt.end(),ostream_iterator cout<<"\nstable_partition:\n"; stable_partition( vecInt.begin(),vecInt.end(),bind2nd( modulus copy( vecInt.begin(),vecInt.end(),ostream_iterator system( "pause" ); return 0; }