100分求STL解决办法~~

JeffHe 2006-03-24 05:37:43
偶使用的是VC6.0,使用STL时,碰到如下问题了:
已知一个vector和需要删除元素的下标位置,如何
用erase(remove_if(...))方式来完成该操作?

如:
vector<int> dd;//=[11 12 13 14 15 16 17 18 19]
现在要将dd下标为0,2,4的元素(即11,13,15)删除,
erase(remove_if(...))方式如何解决?是否需要使用
bind2nd()呢?
...全文
271 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
睡在床板下_ 2006-03-25
  • 打赏
  • 举报
回复
ugg(逸学堂(exuetang.net)) ( ) 信誉:100 2006-03-24 19:58:00 得分: 0


for(vector<int>::iterator it = dd.begin(); it != dd.end(); ++it)
{
it = erase(it);
}
----------------------------------
差不多了~~
xlsue 2006-03-25
  • 打赏
  • 举报
回复
我好像没发现有这个函数哦!
我认为可以这样:vector的iterator是随机的,可以使用iterator+下标,从vector的后面往前面移除下标为4,2,0的元素。
我也想看到更好的办法,期待中。。。
JeffHe 2006-03-25
  • 打赏
  • 举报
回复
xlsue(小林):是以下标进行删除~~ 而不是以值进行删除,
不知道如何在remove_if()中访问到vector[]的下标呢?
xlsue 2006-03-25
  • 打赏
  • 举报
回复
我觉得计数器和下标都差不多是同个意思,没有必要砖牛角尖吧?能达到程序意图的可以了
xlsue 2006-03-25
  • 打赏
  • 举报
回复
to 回复人:ricky460(阿酷):
你的程序符合楼主的,学习。
template <typename T>
void PRINT(const T& t)
{
for(typename T::const_iterator iter = t.begin() ; iter != t.end() ; ++ iter)
//这里前面要加typename
{
cout << *iter << " " ;
}
}
ricky460 2006-03-25
  • 打赏
  • 举报
回复
------------------------------------------------------------------------
JeffHe(雅永紫) ( ) 信誉:99 2006-03-25 08:56:00 得分: 0

xlsue(小林):是以下标进行删除~~ 而不是以值进行删除,
不知道如何在remove_if()中访问到vector[]的下标呢?
---------------------------------------------------------------------------

利用distance函数可以通过iterator得到下标 .

vector<int>::iterator iter ;
...........
int iIndex = distance(vInt.begin() , iter); //根据iterator得到索引 . . .



示例代码 :( 利用distance来删除制定下标元素)

int iOffset = 0 ;
for(vector<int>::iterator iter = vInt.begin() ; iter != vInt.end() ; ++ iter)
{
int iIndex = distance(vInt.begin() , iter) + iOffset;
if(iIndex == 0 || iIndex == 2 || iIndex == 4)
{
vInt.erase(iter , iter + 1);
iOffset += 1 ;
}
}

注解: 1: 这里加了一个变量iOffset , 这是因为 , 你在数组里删除一个元素 , 那么删除前下标2的元素 就对应于 删除后 下标1 的元素 . . . 每删除一个 ,就要累加一次 . .
2: 这段代码是有漏洞的 , 但是为了让楼主看得清晰明白 , 我没有加入纠错的代码.这里
需要加入判断是否是删除最后一个元素的代码 , 删除最后一个元素时 ,需要用另外的代码 . 代码很简单 ,就当是功课 , 让楼主自己写吧 . . .
3: 替代方法 :
int iIndex = 0 ;
for(.................)
{
if(iIndex == 0 || iIndex == 2 || iIndex == 4) DoSomething();
iIndex ++ ;
}
这种方法是最简单的 ,但我想 , 这并非是楼主所想要的 . . .


ricky460 2006-03-25
  • 打赏
  • 举报
回复
问题: 已知 vector , 和下标 , 利用erase , remove_if 删除元素 .
解决代码:
--------------------------------------------
#include "stdafx.h"
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std ;

//打印函数
template <typename T>
void PRINT(const T& t)
{
for(T::const_iterator iter = t.begin() ; iter != t.end() ; ++ iter)
{
cout << *iter << " " ;
}
}

//设置删除条件的仿函数
class DEL
{
int iIndex ; //定义一个iIndex来模拟vector的索引.
public:
DEL(){ iIndex = 0 ; }
bool operator()(int )
{
bool bReturn = (iIndex == 0 || iIndex == 2 || iIndex == 4) ;
iIndex ++ ;
return bReturn ;
}
};

int main(int argc, char* argv[])
{
vector <int> vInt ;

for(int i = 11 ; i <= 19 ; i ++) vInt.push_back(i);

PRINT(vInt);

cout << endl << endl;

vInt.erase(remove_copy_if(vInt.begin() , vInt.end() , vInt.begin(), DEL()), vInt.end());

PRINT(vInt);

return 0;
}

----------------------------------------------
{ 如上代码在 VC6 ,WindowXP 下测试成功 }

注解:

1: 用了一个条件判断仿函数DEL , 在DEL中定义了一个iIndex来模拟vector的索引 , 在
vInt.erase中 , vInt每向后移动一个元素 , 就会调用一次 DEL.operator()(int );
DEL.iIndex就会递增一次 , 即 , iIndex是跟实际vector的索引是相符的 . . . . .
2: 这里用remove_copy_if来代替remove_if ,是因为,STL中 , remove_if 是一个比较特殊的
函数 , 它会在内部调用两次传进去的比较函数 . 即内部类似于:
remove_if(....)
{
find_if(.... , DEL)
.......
return remove_copy_if(.... , DEL) ;
}
由于DEL是传递值而非传地址 ,所以这里在计算iIndex会出现问题 . 所以 , 在这里我用
remove_copy_if来代替了remove_if . 楼主可以不用考虑这些具体细节 . . .


以上代码可以实现楼主的需求. 楼主可以修改一下,以满足动态传入删除元素的下标的需求 .
howyougen 2006-03-24
  • 打赏
  • 举报
回复
guangmingshizhe(流云飞翼) ( ) 说的对
删除一个元素后,元素的下标已经发生改变了,这是问题所在吧


using namespace std;

struct mycond
{
mutable int i;
mycond(){i=-1;}
bool operator()(int) const
{
i++;
return (i%2 == 0) && (i<5) ;
}
};

int main()
{
//0,2,4的元素(即11,13,15)删除
int a[] = {11, 12, 13, 14, 15, 16, 17, 18, 19};
vector<int> dd(a, a + sizeof(a)/sizeof(a[0]) );//=[11 12 13 14 15 16 17 18 19]
for(vector<int>::iterator it = dd.begin(); it != dd.end(); ++it)
{
cout<< *it<< " ";
}
cout<< endl;

replace_if(dd.begin(), dd.end(), mycond(),-1234567); //先替换成-1234567
dd.erase(remove(dd.begin(),dd.end(),-1234567),dd.end()); //再删除

for(vector<int>::iterator it = dd.begin(); it != dd.end(); ++it)
{
cout<< *it<< " ";
}
cout<< endl;
system("pause");
}
guyanhun 2006-03-24
  • 打赏
  • 举报
回复
dd.erase(remove_if(dd.begin(), dd.end(),compose2( std::logical_and<bool>(),std::bind2nd(std::modulus<int>() ,2),std::bind2nd(std::less<int>(),16) ) ), dd.end());

guyanhun 2006-03-24
  • 打赏
  • 举报
回复
dd.erase(remove_if(dd.begin(), dd.end(),compose2( logical_and<bool>(),bind2nd(modulus<int>() ,2),bind2nd(less<int>(),16) ), dd.end());
xlsue 2006-03-24
  • 打赏
  • 举报
回复
ugg(逸学堂(exuetang.net)) ( ) 信誉:100 2006-03-24 19:58:00 得分: 0


for(vector<int>::iterator it = dd.begin(); it != dd.end(); ++it)
{
it = erase(it);
}
------------------------------------------
打断一下,上面的代码是啥意思? 有erase(Iterator)这个函数?上面的代码好像有bug哦?


xlsue 2006-03-24
  • 打赏
  • 举报
回复
不明白楼主是想以下标0,2,4删除还是以值删除?
逸学堂 2006-03-24
  • 打赏
  • 举报
回复
for(vector<int>::iterator it = dd.begin(); it != dd.end(); ++it)
{
it = erase(it);
}
xiaocai0001 2006-03-24
  • 打赏
  • 举报
回复
MSDN上的一个例子:
......
Numbers[0] = 10 ;
Numbers[1] = 20 ;
Numbers[2] = 10 ;
Numbers[3] = 15 ;
Numbers[4] = 12 ;
Numbers[5] = 7 ;
Numbers[6] = 9 ;
Numbers[7] = 10 ;


cout << "Before calling remove_if" << endl ;

// print content of Numbers
cout << "Numbers { " ;
for(it = start; it != end; it++)
cout << *it << " " ;
cout << " }\n" << endl ;

// remove all elements from Numbers that <= 10
last = remove_if(start, end, bind2nd(less_equal<int>(), 10) ) ;
......

一般用remove_if操作时, 对容器内元素的值有条件判定的, 像你这样的只是对容器的下标操作时, 可以直接用迭代器找到对应的下标, 然后erase()就可以了
妍妍 2006-03-24
  • 打赏
  • 举报
回复
删除一个元素后,元素的下标已经发生改变了,这是问题所在吧
citywanderer2005 2006-03-24
  • 打赏
  • 举报
回复
remove_if(dd.begin(), dd.end(), greater)
表示删除整个vector中满足条件(即使greater函数为真)的元素,它的返回值是被删除元素后的第二个元素的iterator。因为remove不会改变vector的size,所以最后空留的空间由原vector中的最后几个元素填充,这里就要用erase删除后面的重复的元素。
citywanderer2005 2006-03-24
  • 打赏
  • 举报
回复
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
bool greater( int value )
{
return (value == 11 || value == 13 || value == 15);
}

int main()
{
//0,2,4的元素(即11,13,15)删除
int a[] = {11, 12, 13, 14, 15, 16, 17, 18, 19};
vector<int> dd(a, a + sizeof(a)/sizeof(a[0]) -1);//=[11 12 13 14 15 16 17 18 19]
for(vector<int>::iterator it = dd.begin(); it != dd.end(); ++it)
{
cout<< *it<< " ";
}
cout<< endl;

dd.erase(remove_if(dd.begin(), dd.end(), greater), dd.end());

for(vector<int>::iterator it = dd.begin(); it != dd.end(); ++it)
{
cout<< *it<< " ";
}
cout<< endl;
}
jiezhi 2006-03-24
  • 打赏
  • 举报
回复
这样的问题还是看看STL Ref吧
expert2000 2006-03-24
  • 打赏
  • 举报
回复
好贴。我也不懂。正好学习学习

64,650

社区成员

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

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