C++ 基于条件拆分STL列表
我有一个std::列表,如下所示(x标记表示一些小于500的数字) 我现时的守则如下:C++ 基于条件拆分STL列表,c++,algorithm,list,vector,stl,C++,Algorithm,List,Vector,Stl,我有一个std::列表,如下所示(x标记表示一些小于500的数字) 我现时的守则如下: list<int> templist; vector<list<int> > v; for(list<int>::iterator lit=originallist.begin(); lit!=oriniallist.end(); ++lit) { if (*lit > 500) { templist.push_back(*lit)
list<int> templist; vector<list<int> > v;
for(list<int>::iterator lit=originallist.begin(); lit!=oriniallist.end(); ++lit) {
if (*lit > 500) {
templist.push_back(*lit);v.push_back(templist); templist.clear(); continue;
}
templist.push_back(*lit);
}
列表模板;向量v;
对于(列表::迭代器lit=originallist.begin();lit!=oriniallist.end();++lit){
如果(*点亮>500){
templast.push_back(*亮);v.push_back(templast);templast.clear();continue;
}
圣殿骑士。推回(*亮);
}
<>在没有使用TEPLPLIST的情况下,C++中实现以上任务的最有效方法是什么?非常感谢您的帮助。请尝试以下方法
#include <vector>
#include <list>
#include <algorithm>
#include <functional>
//...
auto first = YourList.begin();
while ( first != YourList.end() )
{
auto last = std::find_if( first, YourList.end(), std::bind2nd( std::greater<int>(), 500 ) );
if ( last != YourList.end() ) ++last;
YourVector.push_back( std::list<int>( first, last ) );
first = last;
}
#包括
#包括
#包括
#包括
//...
auto first=YourList.begin();
while(first!=YourList.end())
{
auto last=std::find_if(首先,YourList.end(),std::bind2nd(std::greater(),500));
如果(last!=YourList.end())+last;
YourVector.push_back(std::list(first,last));
第一个=最后一个;
}
lst.splice( newLst.begin(), newLst, lst.begin(), lst.begin() + sliceLength);
std::list::splice
并移动迭代器,直到找到iter或到达iter
#include <iostream>
#include <list>
#include <vector>
std::vector< std::list<int> > & split( std::list<int> v,
int delim, std::vector< std::list<int> >& elems) {
auto it = v.begin();
while ( it != v.end()) {
std::list<int> l;
while ( it != v.end() && *it < delim) {
++it;
}
if( it != v.end()) {
l.splice( l.begin(), v, v.begin(), ++it);
it = v.begin();
} else {
l.splice( l.begin(), v, v.begin(), it);
}
elems.push_back( l);
}
return elems;
}
std::vector< std::list<int> > split( const std::list<int> &v, int delim) {
std::vector< std::list<int> > elems;
split( v, delim, elems);
return elems;
}
用法:
int main() {
std::list<int> v = { 1, 2, 3, 503, 5, 6, 502, 7, 510, 3, 500, 6, 7};
std::vector< std::list<int> > vl;
vl = split( v, 500);
int i = 0;
while( i < vl.size()) {
std::list<int>::const_iterator it = vl[ i].begin();
while( it != vl[ i].end())
std::cout << *it++;
std::cout << std::endl;
++i;
}
return 0;
}
int main() {
std::list<int> v = { 1, 2, 3, 503, 5, 6, 502, 7, 510, 3, 500, 5, 9};
std::vector< std::list<int> > vl;
vl = split( v, 500);
int i = 0;
while( i < vl.size()) {
std::list<int>::const_iterator it = vl[ i].begin();
while( it != vl[ i].end())
std::cout << *it++;
++i;
}
return 0;
}
int main() {
std::list<int> v = { 1, 2, 3, 503, 5, 6, 502, 7, 510, 3, 500, 5, 9};
std::vector< std::list<int> > vl;
vl = split( v, 500);
int i = 0;
while( i < vl.size()) {
std::list<int>::const_iterator it = vl[ i].begin();
while( it != vl[ i].end())
std::cout << *it++;
++i;
}
return 0;
}
用法:
int main() {
std::list<int> v = { 1, 2, 3, 503, 5, 6, 502, 7, 510, 3, 500, 6, 7};
std::vector< std::list<int> > vl;
vl = split( v, 500);
int i = 0;
while( i < vl.size()) {
std::list<int>::const_iterator it = vl[ i].begin();
while( it != vl[ i].end())
std::cout << *it++;
std::cout << std::endl;
++i;
}
return 0;
}
int main() {
std::list<int> v = { 1, 2, 3, 503, 5, 6, 502, 7, 510, 3, 500, 5, 9};
std::vector< std::list<int> > vl;
vl = split( v, 500);
int i = 0;
while( i < vl.size()) {
std::list<int>::const_iterator it = vl[ i].begin();
while( it != vl[ i].end())
std::cout << *it++;
++i;
}
return 0;
}
int main() {
std::list<int> v = { 1, 2, 3, 503, 5, 6, 502, 7, 510, 3, 500, 5, 9};
std::vector< std::list<int> > vl;
vl = split( v, 500);
int i = 0;
while( i < vl.size()) {
std::list<int>::const_iterator it = vl[ i].begin();
while( it != vl[ i].end())
std::cout << *it++;
++i;
}
return 0;
}
intmain(){
列表v={1,2,3503,5,6502,7510,3500,5,9};
std::vectorvl;
vl=分裂(v,500);
int i=0;
而(i std::cout虽然此解决方案使用临时的std::list
,但它不分配列表节点元素,在C++03情况下只分配1个内存(C++11情况根据返回值的大小分配对数个内存)
这是一个C++03解决方案。一个C++11解决方案可以一次性完成
bool big_as_500( int x ) {return x>=500;}
std::vector< std::list< int > > do_stuff( std::list<int>& original_list ) {
// we have to do this, because resizing the return value involves lots of allocations
// and stuff in C++03, so make sure we get the size right by precalculating it:
std::size_t count = std::count_if( originallist.begin(), originallist.end(), big_as_500 );
std::vector< std::list< int > > result;
result.reserve(count+1);
typedef std::list<int>::const_iterator const_iterator;
std::list< int > current;
for(const_iterator it= originallist.begin(); it!=originallist.end();/*nothing*/) {
++it; // about to invalidate it! (or move lists)
current.splice( current.end(), originallist, originallist.begin() ); // O(1) no memory allocation
if (big_as_500(current.back())) {
result.push_back( std::list<int>() );
current.swap( result.back() );
}
}
// original problem does not specify what to do if the original list does not end
// with an element "big_as_500", so I'll just drop them
return result; // rely on NRVO to eliminate the copy here, if your compiler does not
// support it, take result as a reference parameter.
}
template<typename T, typename A>
void efficient_grow_by_1( std::vector<T,A>& make_one_bigger ) {
if (make_one_bigger.size()+1 > make_one_bigger.capacity() )
{
std::vector<T, A> swap_vec;
swap_vec.reserve( (make_one_bigger.size()+1)*5/3 );
for (std::vector<T, A>::iterator it = make_one_bigger.begin(); it != make_one_bigger.end(); ++it ) {
using std::swap;
swap_vec.push_back();
std::swap( *it, swap_vec.back() );
}
swap_vec.swap( make_one_bigger );
}
make_one_bigger.push_back();
}
void do_stuff( std::list<int>& original_list, std::vector< std::list< int > >& result ) {
typedef std::list<int>::const_iterator const_iterator;
std::list< int > current;
for(const_iterator it= originallist.begin(); it!=originallist.end();) {
++it;
current.splice( current.end(), originallist, originallist.begin() ); // O(1) no memory allocation
if (current.back()>=500) {
efficient_grow_by_1(result);
current.swap( result.back() );
}
}
// original problem does not specify what to do if the original list does not end
// with an element "big_as_500", so I'll just drop them
}
bool big_as_500(int x){return x>=500;}
std::vector>做些什么(std::list和原始列表){
//我们必须这样做,因为调整返回值需要大量的分配
//C++03中的内容,因此请确保通过预先计算得到正确的大小:
std::size\u t count=std::count\u if(originalist.begin()、originalist.end()、big\u as\u 500);
std::vector>结果;
结果:储备(计数+1);
typedef std::list::const_迭代器const_迭代器;
标准::列表当前;
for(const_iterator it=originallist.begin();it!=originallist.end();/*nothing*/){
++it;//即将使其无效!(或移动列表)
current.splice(current.end(),originallist,originallist.begin());//O(1)没有内存分配
if(大的作为500(current.back())){
result.push_back(std::list());
current.swap(result.back());
}
}
//原始问题没有指定如果原始列表没有结束该怎么办
//有一个元素“big_as_500”,所以我就把它们扔了
return result;//如果编译器不执行此操作,请依赖NRVO消除此处的副本
//支持它,将结果作为参考参数。
}
C++11解决方案:
std::vector< std::list< int > > do_stuff( std::list<int>& original_list ) {
std::vector< std::list< int > > result;
typedef std::list<int>::const_iterator const_iterator;
std::list< int > current;
for(const_iterator it= originallist.begin(); it!=originallist.end();/*nothing*/) {
++it;// about to become invalid/in wrong list
current.splice( current.end(), originallist, originallist.begin() ); // O(1) no memory allocation
if (current.back() >= 500) {
result.emplace_back( std::move(current) );
}
}
// original problem does not specify what to do if the original list does not end
// with an element "big_as_500", so I'll just drop them
return result; // will NRVO, or move, so no worries
}
std::vector>do_stuff(std::list和原始_列表){
std::vector>结果;
typedef std::list::const_迭代器const_迭代器;
标准::列表当前;
for(const_iterator it=originallist.begin();it!=originallist.end();/*nothing*/){
++它;//即将失效/在错误列表中
current.splice(current.end(),originallist,originallist.begin());//O(1)没有内存分配
if(current.back()>=500){
结果:向后放置(标准::移动(当前));
}
}
//原始问题没有指定如果原始列表没有结束该怎么办
//有一个元素“big_as_500”,所以我就把它们扔了
返回结果;//将NRVO或move,因此无需担心
}
在C++11中,调整大小相对便宜,所以我们很好
现在,我们可以非常喜欢C++03,并模仿C++11的功能,一次完成所有工作
bool big_as_500( int x ) {return x>=500;}
std::vector< std::list< int > > do_stuff( std::list<int>& original_list ) {
// we have to do this, because resizing the return value involves lots of allocations
// and stuff in C++03, so make sure we get the size right by precalculating it:
std::size_t count = std::count_if( originallist.begin(), originallist.end(), big_as_500 );
std::vector< std::list< int > > result;
result.reserve(count+1);
typedef std::list<int>::const_iterator const_iterator;
std::list< int > current;
for(const_iterator it= originallist.begin(); it!=originallist.end();/*nothing*/) {
++it; // about to invalidate it! (or move lists)
current.splice( current.end(), originallist, originallist.begin() ); // O(1) no memory allocation
if (big_as_500(current.back())) {
result.push_back( std::list<int>() );
current.swap( result.back() );
}
}
// original problem does not specify what to do if the original list does not end
// with an element "big_as_500", so I'll just drop them
return result; // rely on NRVO to eliminate the copy here, if your compiler does not
// support it, take result as a reference parameter.
}
template<typename T, typename A>
void efficient_grow_by_1( std::vector<T,A>& make_one_bigger ) {
if (make_one_bigger.size()+1 > make_one_bigger.capacity() )
{
std::vector<T, A> swap_vec;
swap_vec.reserve( (make_one_bigger.size()+1)*5/3 );
for (std::vector<T, A>::iterator it = make_one_bigger.begin(); it != make_one_bigger.end(); ++it ) {
using std::swap;
swap_vec.push_back();
std::swap( *it, swap_vec.back() );
}
swap_vec.swap( make_one_bigger );
}
make_one_bigger.push_back();
}
void do_stuff( std::list<int>& original_list, std::vector< std::list< int > >& result ) {
typedef std::list<int>::const_iterator const_iterator;
std::list< int > current;
for(const_iterator it= originallist.begin(); it!=originallist.end();) {
++it;
current.splice( current.end(), originallist, originallist.begin() ); // O(1) no memory allocation
if (current.back()>=500) {
efficient_grow_by_1(result);
current.swap( result.back() );
}
}
// original problem does not specify what to do if the original list does not end
// with an element "big_as_500", so I'll just drop them
}
模板
void-efficient按1增长(std::vector&使一个更大){
if(make_one_bigger.size()+1>make_one_bigger.capacity())
{
标准::向量交换向量;
交换向量储备((使一个更大的向量大小()+1)*5/3);
对于(std::vector::iterator it=make_one_bigger.begin();it!=make_one_bigger.end();+it){
使用std::swap;
交换向量。向后推();
std::swap(*it,swap_vec.back());
}
交换向量交换(使一个更大);
}
再大一点。把你推回去();
}
void do_stuff(标准::列表和原始列表,标准::向量<标准::列表>和结果){
typedef std::list::const_迭代器const_迭代器;
标准::列表当前;
for(const_iterator it=originallist.begin();it!=originallist.end();){
++它;
current.splice(current.end(),originallist,originallist.begin());//O(1)没有内存分配
if(current.back()>=500){
有效的增长率为1(结果);
current.swap(result.back());
}
}
//原始问题没有指定如果原始列表没有结束该怎么办
//有一个元素“big_as_500”,所以我就把它们扔了
}
这太疯狂了,所以我建议升级你的编译器
这里的诀窍是,我们用一次一个元素的拼接来填充“临时”列表。因为std::list::splice
的(大多数?)实现最终不得不遍历元素来计数它们(这在C++11中是必需的,在C++03中是常见的),在确定要放入下一个块中的元素时,一次执行一个操作是合理有效的。每个节点直接来自输入列表,并被收集到临时列表中(无内存分配)
一旦我们建立了这个列表,我们直接将它交换到列表的输出向量中。这避免了任何内存分配,除了我