边遍历容器边删除容器元素——适用于…

本文介绍了一种在 C++ STL 的 list、set 和 map 容器中高效删除指定元素的方法,并提供了自动化测试代码验证该方法的有效性和可靠性。
    我们有时候想要删除容器中的多个元素。普通做法可能是逐个进行删除。但这要做的话效率比较低。其实std中的list、set和map容器是有办法边遍历边删除的。使用这种方法,优点很明显,高效省事。缺点就是这种用法并没有出现在标准库的文档中。虽然经测试,windows vs2005 vs2008,gcc4.1下都可以pass。但日后编译器升级了就不一定了。但我觉得这个hack应该会保留下去,因为太方便了。
    for (list<int>::iterator it = lt.begin(); it != lt.end(); ++ j)
        {
            ASSERT_EQ(*it, j);
            if (j == to_delete)
            {
                lt.erase(it++);// 注意,这句话很关键,不能分成两句:lt.erase(it); it++;,否则斯巴达,怎么样非常hack吧哈哈
            }
            else
            {
                ++ it;
            }
        }
    下面是测试这种方法是否可用的自动化测试代码,想用这种方法前现在自己的编译器上编译运行下。如果pass了再用。(注意,其实pass也不一定就ok,因为只测试了1w次,这个可以自己调下)
==========================自动化测试代码的分割线===============================
#include <iostream>
#include <list>
#include <set>
#include <map>
#include <cstdlib>

using namespace std;

#define ASSERT_EQ(X, Y) if(X != Y) {cout << X << " != " << Y << endl;exit(1);}

int main()
{
    for (int times = 0; times < 10000; times ++)
    {
        int element_cnt = (rand() % 1000) + 1;
        int to_delete = rand() % element_cnt;
        list<int> lt;
        for (int i = 0; i < element_cnt; ++ i)
        {
            lt.push_back(i);
        }
        int j = 0;
        for (list<int>::iterator it = lt.begin(); it != lt.end(); ++ j)
        {
            ASSERT_EQ(*it, j);
            if (j == to_delete)
            {
                lt.erase(it++);
            }
            else
            {
                ++ it;
            }
        }
        j = 0;
        for (list<int>::iterator it = lt.begin(); it != lt.end(); ++ j, ++ it)
        {
            if (j < to_delete)
            {
                ASSERT_EQ(j, *it);               
            }
            else
            {
                ASSERT_EQ(j+1, *it);
            }
        }
    }
    cout << "pass test" << endl;

    for (int times = 0; times < 10000; times ++)
    {
        int element_cnt = (rand() % 1000) + 1;
        int to_delete = rand() % element_cnt;
        set<int> st;
        for (int i = 0; i < element_cnt; ++ i)
        {
            st.insert(i);
        }
        int j = 0;
        for (set<int>::iterator it = st.begin(); it != st.end(); ++ j)
        {
            ASSERT_EQ(*it, j);
            if (j == to_delete)
            {
                st.erase(it++);
            }
            else
            {
                ++ it;
            }
        }
        j = 0;
        for (set<int>::iterator it = st.begin(); it != st.end(); ++ j, ++ it)
        {
            if (j < to_delete)
            {
                ASSERT_EQ(j, *it);               
            }
            else
            {
                ASSERT_EQ(j+1, *it);
            }
        }
    }
    cout << "pass test" << endl;

    for (int times = 0; times < 10000; times ++)
    {
        int element_cnt = (rand() % 1000) + 1;
        int to_delete = rand() % element_cnt;
        map<int, int> mp;
        for (int i = 0; i < element_cnt; ++ i)
        {
            mp[i] = i;
        }
        int j = 0;
        for (map<int, int>::iterator it = mp.begin(); it != mp.end(); ++ j)
        {
            ASSERT_EQ(it->first, j);
            if (j == to_delete)
            {
                mp.erase(it++);
            }
            else
            {
                ++ it;
            }
        }
        j = 0;
        for (map<int, int>::iterator it = mp.begin(); it != mp.end(); ++ j, ++ it)
        {
            if (j < to_delete)
            {
                ASSERT_EQ(j, it->first);       
            }
            else
            {
                ASSERT_EQ(j+1, it->first);
            }
        }
    }
    cout << "pass test" << endl; 

    return 0;  
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值