• STL进阶--删除元素


    删除元素

    从vector或deque删除元素

      vector<int> vec = {1, 4, 1, 1, 1, 12, 18, 16}; // 删除所有的1
      for (vector<int>::iterator itr = vec.begin(); itr != vec.end(); ++itr) {
         if ( *itr == 1 ) {
            vec.erase(itr);    //你或许会想到使用erase成员函数
         }
      }   // 的确,是可以达到目的 vec: { 4, 12, 18, 16}
      // 但是复杂度是: O(n*m),每删除一个元素,后面的往前移动
    
      // 如果使用算法remove
      remove(vec.begin(), vec.end(), 1);  // 复杂度 O(n) 
                                          // vec: {4, 12, 18, 16, ?, ?, ?, ?}
    
      
      
      vector<int>::iterator newEnd = remove(vec.begin(), vec.end(), 1);   // 将不删除的元素移到前面,O(n)
      vec.erase(newEnd, vec.end());  //删除最后无用的元素
    
      // 算法remove_if()和unique()也是类似
    
    
      // 此时vec仍然占了8个int空间: vec.capacity() == 8
      vec.shrink_to_fit();   // C++ 11
      // 现在vec.capacity() == 4 
    
      // For C++ 03:
      vector<int>(vec).swap(vec); // 相同效果,释放空的内存
    

    从List删除

      list<int> mylist = {1, 4, 1, 1, 1, 12, 18, 16};
    
      list<int>::iterator newEnd = remove(mylist.begin(), mylist.end(), 1);  // 使用算法remove,O(n)
      mylist.erase(newEnd, mylist.end());
    
    
      mylist.remove(1);  // 成员函数更快,直接操作指针,从链上删除
    

    从关联容器或无序容器中删除

      multiset<int> myset = {1, 4, 1, 1, 1, 12, 18, 16};
    
      multiset<int>::iterator newEnd = remove(myset.begin(), myset.end(), 1);  // O(n)
      myset.erase(newEnd, myset.end()); 
    
      myset.erase(1); // O(log(n)) or O(1)
    

    结论

    • vector或者deque: 算法remove() + erase()
    • list:成员函数remove()
    • 关联容器或者无序容器:成员函数erase()

    删除元素之后

    // 看个关联容器的例子,此程序会发生什么
    multiset<int> s = {1, 4, 1, 1, 1, 12, 18, 16};;
    
    multiset<int>::iterator itr;
    for (itr=s.begin(); itr!=s.end(); itr++) {
       if (*itr == 1) {
          s.erase(itr);      
          cout << "Erase one item of " << *itr << endl;
       } 
    }
    
    // 删除第一个元素成功,后面未定义的行为
    

    解决方法:

    multiset<int>::iterator itr;
    for (itr=s.begin(); itr!=s.end(); ) {
       if (*itr == 1) {
          cout << "Erase one item of " << *itr << endl;
          s.erase(itr++);    //在删除之前,迭代器已经指向下一个
       } else {
          itr++;
       }
    }
    

    对于序列容器

    vector<int> v = {1, 4, 1, 1, 1, 12, 18, 16};
    vector<int>::iterator itr2;
    for (itr2=v.begin(); itr2!=v.end(); ) {
       if (*itr2 == 1) {
          cout << "Erase one item of " << *itr2 << endl;
          v.erase(itr2++);    //这样仍然不安全,删除的元素后面的所有迭代器都失效
       } else {
          itr2++;
       }
    }
    
    

    解决方法:

    for (itr2=v.begin(); itr2!=v.end(); ) {
       if (*itr2 == 1) {
          cout << "Erase one item of " << *itr2 << endl;
          itr2 = v.erase(itr2);    
       } else {
          itr2++;
       }
    }
    
    // 1 序列容器和无序容器的erase返回指向删除元素下一个元素的迭代器
    // 2. 关联容器的erase不返回东西
    

    总结

    • 序列容器和无序容器使用:it = c.erase(it);
    • 关联容器:c.erase(it++);

    使用算法

    vector<int> c = {1, 4, 1, 1, 1, 12, 18, 16};
    
    //普通函数
    bool equalOne(int e) {
       if (e == 1) {
          cout << e << " will be removed" << endl;
          return true;
       }
       return false;
    }
    auto itr = remove_if(c.begin(), c.end(), equalOne);
    c.erase(itr, c.end());
    
    
    
    //使用bind():
    bool equalOne(int e, int pattern) {
       if (e == pattern) {
          cout << e << " will be removed" << endl;
          return true;
       }
       return false;
    }
    remove_if(v.begin(), v.end(), bind(equalOne, placeholders::_1, 1));
    
    
    
    // Lambda函数:
    auto itr = remove_if(v.begin(), v.end(), 
          [](int e){ 
             if(e == 1) {
                cout << e << " will be removed" <<endl; return true; 
             } 
          } 
       );
    
  • 相关阅读:
    如何引用webservice
    oracle TNS 无法启动 解决方案
    android 照相
    Nutch 运行错误
    XML Bitmap
    Level List
    hadoop hdfs 上传下载文件
    Layer List
    android popup
    [置顶] Clean Talk
  • 原文地址:https://www.cnblogs.com/logchen/p/10205623.html
Copyright © 2020-2023  润新知