你发现有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 _BidIt,
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 _BidIt,
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<int> vecInt;
for ( int i = 1;i <= 9;++ i )
{
vecInt.push_back( i );
}
partition( vecInt.begin(),vecInt.end(),bind2nd( modulus<int>(),2 ) );
copy( vecInt.begin(),vecInt.end(),ostream_iterator<int>( cout," " ) );
cout<<"\nstable_partition:\n";
stable_partition( vecInt.begin(),vecInt.end(),bind2nd( modulus<int>(),2 ) );
copy( vecInt.begin(),vecInt.end(),ostream_iterator<int>( cout," " ) );
system( "pause" );
return 0;
}