STL partition 函数的疑问

x642458 2010-03-13 03:38:14

#include <algorithm>
#include <iostream>
using namespace std;
void print(int x){
cout << x << ' ';
}
bool less10(int x){
return x < 10 ? 1 : 0;
}
int main(void){
int iArray[10]={16, -1, 3, 11, 2, 5, 8, 20, 9, 4};
int *result=partition1(iArray, iArray+10, less10);
cout << "按小于10进行分割" << endl;
for_each(iArray, iArray+10, print);
cout <<endl<<"partition算法返回的分界元素为 " << *result <<endl;
return 0;
}
PS:例子可以参加《C++ STL 开发技术导引》P334,例程22_27

在VC6.0 环境下,分别用VC++自带的STL和STLport 库,两个运行结果是一样的!
都是{4, -1, 3, 9, 2, 5, 8, 20, 11, 16}
但两个库实现明显不一样啊

VC 自带STL

template<class _BI, class _Pr> inline
_BI partition1(_BI _F, _BI _L, _Pr _P)
{for (; ; ++_F)
{for (; _F != _L && _P(*_F); ++_F)
;
if (_F == _L)
break;
for (; _F != --_L && !_P(*_L); )
;
if (_F == _L)
break;
iter_swap(_F, _L); }
return (_F); }


STLport

template <class _ForwardIter, class _Predicate>
_STLP_INLINE_LOOP _ForwardIter __partition(_ForwardIter __first,
_ForwardIter __last,
_Predicate __pred,
const forward_iterator_tag &) {
if (__first == __last) return __first;

while (__pred(*__first))
if (++__first == __last) return __first;

_ForwardIter __next = __first;

while (++__next != __last) {
if (__pred(*__next)) {
_STLP_STD::swap(*__first, *__next);
++__first;
}
}
return __first;
}

很明显啊,调用后VC STL后,第一个数是 4 没错,
但调用STLport partition后,第一个数应该是 -1

那个高手解释下,只用解释为什么调用STLport partition后, 第一个数不是-1就行。
...全文
282 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
cattycat 2010-03-13
  • 打赏
  • 举报
回复
就是调用的时候看它具体调用了哪个,可能没调用你说的那个stlport的。
x642458 2010-03-13
  • 打赏
  • 举报
回复
结果出来了,如fox000002 所说,有两种partition,在调用时,函数自动判断,
迭代器是前向的还是双向的。跟踪发现,它调用的是双向迭代器的函数,显然这样的效率要高点。
fox000002 2010-03-13
  • 打赏
  • 举报
回复
反正都是模板实现,lz 大可修改 stlport 的代码,输出些中间变量
x642458 2010-03-13
  • 打赏
  • 举报
回复
关于我实验环境的问题,有下面的代码:
#include <algorithm>
#include <iostream>
using namespace std;
void print(int x){
cout << x << ' ';
}
bool less10(int x){
return x < 10 ? 1 : 0;
}
int main(void){
int iArray[10]={16, -1, 3, 11, 2, 5, 8, 20, 9, 4};
int *result=partition1(iArray, iArray+10, less10);
cout << "按小于10进行分割" << endl;
for_each(iArray, iArray+10, print);
cout <<endl<<"partition算法返回的分界元素为 " << *result <<endl;

const int len=sizeof(iArray)/sizeof(int);
cout<<"-----------------,查找第7个元素"<<endl;
nth_element(iArray,iArray+6,iArray+len);
for_each(iArray, iArray+10, print);
cout << endl;
return 0;
}

运行上面的源码,输出结果是:
按小于10进行分割
4 -1 3 9 2 5 8 20 11 16
partition算法返回的分界元素为 20
-----------------,查找第7个元素
4 -1 3 5 2 8 9 11 16 20

大家都知道的VC STL的nth_element函数在调用时,
会自动判断数组元素个数,如果元素个数小于16,它会自动由小到大进行排序,
这里调用后没有进行排序,我想可以一定程度上可以认为,我的STLport配置没有问题......

ps:源代码都在库里,不知道怎么把中间变量打印出来,
难道是像上面一样,把函数源码copy出来,放在外面进行调用?
mstlq 2010-03-13
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 x642458 的回复:]
我再补充点吧,我之前曾按mstlq方法试过的,答案的确是{-1 3 2 5 8 9 4 20 11 16},
但调用STLport 的partition 函数后,真真切切是下面的结果:

C/C++ code
按小于10进行分割
4 -1 3 9 2 5 8 20 11 16
partition算法返回的分界元素为 20


C/C++ code
template <class……
[/Quote]

建议楼主单步debug一下,看看跑的具体是怎样的代码……
fox000002 2010-03-13
  • 打赏
  • 举报
回复
看了 __partition 的源代码

stlport 有两种实现

一种是向前推进的,就是 lz 给的代码

另一种就是前后双向推进的,和 VC 的实现类似
x642458 2010-03-13
  • 打赏
  • 举报
回复
我再补充点吧,我之前曾按mstlq方法试过的,答案的确是{-1 3 2 5 8 9 4 20 11 16}
但调用STLport 的partition 函数后,真真切切是下面的结果:
按小于10进行分割
4 -1 3 9 2 5 8 20 11 16
partition算法返回的分界元素为 20


template <class _ForwardIter, class _Predicate>
_ForwardIter partition(_ForwardIter __first, _ForwardIter __last, _Predicate __pred) {
_STLP_DEBUG_CHECK(_STLP_PRIV __check_range(__first, __last))
return _STLP_PRIV __partition(__first, __last, __pred, _STLP_ITERATOR_CATEGORY(__first, _ForwardIter));
}

我现在怀疑,是不是上面这个函数调用__partition后,
才产生{4 -1 3 9 2 5 8 20 11 16}的结果,
但这个函数貌似只含有几个宏,其他就没有什么了嘛....

想看看关于STLport partition函数源码的,可以留下邮箱,欢迎大家多讨论!
xboy 2010-03-13
  • 打赏
  • 举报
回复
同意:mstlq
请检查实验环境,调试一下程序,把中间变量变化都打出来
mstlq 2010-03-13
  • 打赏
  • 举报
回复
如果楼主给出的stlport源码没错的话,第一个数确实应该是-1!!
请楼主检查一下试验环境,看看是否定位到了真正被使用的代码……

参考下面代码
输出

按小于10进行分割
-1 3 2 5 8 9 4 20 11 16
partition算法返回的分界元素为 20

#include <algorithm>
#include <iostream>
using namespace std;

void print(int x)
{
cout << x << ' ';
}
int *mypartition(int *first,int *last,const int & p);

int main(void)
{
int iArray[10]= {16, -1, 3, 11, 2, 5, 8, 20, 9, 4};
int *result=mypartition(iArray, iArray+10, 10);
cout << "按小于10进行分割" << endl;
for_each(iArray, iArray+10, print);
cout <<endl<<"partition算法返回的分界元素为 " << *result <<endl;
return 0;
}


int *mypartition(int *first,int *last,const int &p)
{
if (first == last) return first;

while ((*first)<p)
if (++first == last) return first;

int * next = first;

while (++next != last) {
if ((*next)<p) {
std::swap(*first, *next);
++first;
}
}
return first;
}

64,654

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧