最近碰到挺多字典排序的问题,所以就去研究了下stl中next_permutation和prev_permutation的原码.
很强,很会观察,有想法,很仔细,每一步都进行越界检测.毕竟老司机.
得多看看stl原码才行,这可都是干货啊.
先贴个代码.
template<class _BidIt> inline
bool _Next_permutation(_BidIt _First, _BidIt _Last)
{ // permute and test for pure ascending, using operator<
//-----------------------------------------------\
_DEBUG_RANGE(_First, _Last);
_BidIt _Next = _Last;
if (_First == _Last || _First == --_Next)
return (false);
//进行检测,看是否是有效的空间
//-----------------------------------------------/
for (; ; )
{ // find rightmost element smaller than successor
//从右开始找出两两相邻的,左边大于右边的第一对数,记左边的为_Next
_BidIt _Next1 = _Next;
if (_DEBUG_LT(*--_Next, *_Next1))
{ // swap with rightmost element that's smaller, flip suffix
_BidIt _Mid = _Last;
//找右边第一个比_Next大的数,记为_Mid
for (; !_DEBUG_LT(*_Next, *--_Mid); )
;
//交换_Next和_Mid
std::iter_swap(_Next, _Mid);
//翻转_Next之后的数据
std::reverse(_Next1, _Last);
return (true);
}
//要是没法按字典向下排序了,就翻转回从小到大的样子,并标记无法向后翻转
if (_Next == _First)
{ // pure descending, flip all
std::reverse(_First, _Last);
return (false);
}
}
}
prev_permutation和next_permutation的思路是差不多的,也是从右向左找第一对左边大于右边的数,然后在它之后从右往左找比他小的最大的数,与之交换,最后再翻转后面的数就行.