zoukankan      html  css  js  c++  java
  • vector类、迭代器、bitset类(转载)

     

    vector容器类型

       vector容器是一个模板类,可以存放任何类型的对象(但必须是同一类对象)。vector对象可以在运行时高效地添加元素,并且vector中元素是连续存储的。
     
       与对string类对象的介绍一样,仍然使用简化原型(主要是抛弃了分配器模板参数,使用默认的)。
     
    vector的构造
     
    函数原型:
    template<typename T>
       explicit vector();                                 // 默认构造函数,vector对象为空
       explicit vector(size_type n, const T& v = T());    // 创建有n个元素的vector对象
       vector(const vector& x);
       vector(const_iterator first, const_iterator last);

    注:vector容器内存放的所有对象都是经过初始化的。如果没有指定存储对象的初始值,那么对于内置类型将用0初始化,对于类类型将调用其默认构造函数进行初始化(如果有其它构造函数而没有默认构造函数,那么此时必须提供元素初始值才能放入容器中)。
     
    举例:
    vector<string> v1;         // 创建空容器,其对象类型为string类
    vector<string> v2(10);     // 创建有10个具有初始值(即空串)的string类对象的容器
    vector<string> v3(5, "hello"); // 创建有5个值为“hello”的string类对象的容器
    vector<string> v4(v3.begin(), v3.end());  // v4是与v3相同的容器(完全复制)
     
    vector的操作(下面的函数都是成员函数)
     
    bool empty() const;                    // 如果为容器为空,返回true;否则返回false
    size_type max_size() const;            // 返回容器能容纳的最大元素个数
    size_type size() const;                // 返回容器中元素个数 
    size_type capacity() const;            // 容器能够存储的元素个数,有:capacity() >= size() 
    void reserve(size_type n);             // 确保capacity() >= n
    void resize(size_type n, T x = T());   // 确保返回后,有:size() == n;如果之前size()<n,那么用元素x的值补全。
     
    reference front();                     // 返回容器中第一个元素的引用(容器必须非空)
    const_reference front() const;                  
    reference back();                      // 返回容器中最后一个元素的引用(容器必须非空)
    const_reference back() const;
     
    reference operator[](size_type pos);   // 返回下标为pos的元素的引用(下标从0开始;如果下标不正确,则属于未定义行为。
    const_reference operator[](size_type pos) const;
    reference at(size_type pos);           // 返回下标为pos的元素的引用;如果下标不正确,则抛出异常out_of_range
    const_reference at(size_type pos) const;
               
    void push_back(const T& x);            // 向容器末尾添加一个元素         
    void pop_back();                       // 弹出容器中最后一个元素(容器必须非空)
     
    // 注:下面的插入和删除操作将发生元素的移动(为了保持连续存储的性质),所以之前的迭代器可能失效
    iterator insert(iterator it, const T& x = T());        // 在插入点元素之前插入元素(或者说在插入点插入元素)
    void insert(iterator it, size_type n, const T& x);     // 注意迭代器可能不再有效(可能重新分配空间)
    void insert(iterator it, const_iterator first, const_iterator last);
     
    iterator erase(iterator it);           // 删除指定元素,并返回删除元素后一个元素的位置(如果无元素,返回end())
    iterator erase(iterator first, iterator last); // 注意:删除元素后,删除点之后的元素对应的迭代器不再有效。
     
    void clear() const;                    // 清空容器,相当于调用erase( begin(), end())
     
    void assign(size_type n, const T& x = T());   // 赋值,用指定元素序列替换容器内所有元素
    void assign(const_iterator first, const_iterator last);
     
    const_iterator begin() const;          // 迭代序列
    iterator begin();
    const_iterator end() const;
    iterator end();
     
    const_reverse_iterator rbegin() const;
    reverse_iterator rbegin();
    const_reverse_iterator rend() const;
    reverse_iterator rend();
     
    vector对象的比较(非成员函数)
     
       针对vector对象的比较有六个比较运算符:operator==、operator!=、operator<、operator<=、operator>、operator>=。
     
       其中,对于operator==和operator!=,如果vector对象拥有相同的元素个数,并且对应位置的元素全部相等,则两个vector对象相等;否则不等。
       对于operator<、operator<=、operator>、operator>=,采用字典排序策略比较。

    注:其实只需要实现operator==和operator!=就可以了,其它可以根据这两个实现。因为,operator!=(lhs, rhs) 就是 !(lhs == rhs),operator<=(lhs, rhs) 就是 !(rhs < lhs),operator>(lhs, rhs) 就是 (rhs < lhs),operator>=(lhs, rhs) 就是 !(lhs, rhs)。
     
    vector类的迭代器

       vector类的迭代器除了支持通用的前缀自增运算符外,还支持算术运算:it + n、it - n、it2 - it1。注意it2 - it1返回值为difference_type(signed类型)。
     
       注意,任何改变容器大小的操作都可能造成以前的迭代器失效。
     
    应用示例
     

    #include <iostream>
    #include <cassert>
    #include <vector>

    using namespace std;

    int main()
    {
        vector<string> v(5, "hello");
        vector<string> v2(v.begin(), v.end());
        
        assert(v == v2);
        
        cout<<"> Before operation"<<endl;
        for(vector<string>::const_iterator it = v.begin(); it < v.end(); ++it)
            cout<<*it<<endl;
        
        v.insert(v.begin() + 3, 4, "hello, world");
        cout<<"> After insert"<<endl;
        for(vector<string>::size_type i = 0; i < v.size(); ++i)
            cout<<v[i]<<endl;
        
        vector<string>::iterator it = v.erase(v.begin() + 3, v.begin() + 6);
        assert(*it == "hello, world");
        cout<<"> After erase"<<endl;
        for(vector<string>::size_type i = 0; i != v.size(); ++i)
            cout<<v[i]<<endl;
        
        assert(v.begin() + v.size() == v.end());
        assert(v.end() - v.size() == v.begin());
        assert(v.begin() - v.end() == -vector<string>::difference_type(v.size()));
        
        return 0;
    }

    程序说明:上面程序中用了三个循环输出容器中的元素,每个循环的遍历方式是不一样的。特别需要说明的是,第二个循环在条件判断中使用了size()函数,而不是在循环之前先保存在变量中再使用。之所以这样做,有两个原因:其一,如果将来在修改程序时,在循环中修改了容器元素个数,这个循环仍然能很好地工作,而如果先保存size()函数值就不正确了;其二,由于这些小函数(其实现只需要一条返回语句)基本上都被声明为inline,所以不需要考虑效率问题。


    迭代器

       迭代器(iterator)是用来遍历容器内所有元素的数据类型。标准库为每一种标准容器定义了一种迭代器类型。迭代器类型提供了比下标操作更通用的方法:所有标准容器类都定义了相应的迭代器类型,而只有少数的容器支持下标操作。所以,在编写C++程序时,用迭代器遍历容器是一种更通用的方法,也更加安全。一般提供两种类型:iterator和const_iterator。

    begin()和end()操作

       每种容器都定义了一对命名为begin()和end()的函数,用来返回容器的迭代序列。其中,begin返回的迭代器指向第一个元素,end返回的迭代器指向最后一个元素的下一个位置(实际上是一个不存在的元素),所以迭代序列为[begin(), end())。如果容器为空,那么begin()返回与end()一样的迭代器。

    访问容器元素(operator*)

       假如迭代器it指向容器的一个元素,那么解引用*it就是该元素的值(注意,不能对end()解引用)。

    下一个元素(operator++)

       所有迭代器都支持前缀自增运算符,如++it,表示把迭代器移到容器中的下一个元素的位(同样不能对end()运算)。

    比较 (operator == or operator !=)

       所有迭代器都支持迭代器之间的比较:
       operator ==:如果两个迭代器指向同一元素,那么返回true;否则返回false。(operator != 类似)


    bitset模板类

    template<size_t N>
        class bitset;

       bitset也是类模板,其模板参数N必须是常量表达式(能够在编译时计算出其值),表示bitset类对象的长度(位的个数)。bitset对象用来作为位容器,方便对位的操作,其元素为位。bitset对象元素的位置编号从 0 到 N - 1,对应着位串从低位到高位。

    bitset类对象的构造

    它有三个构造函数:

    bitset();   

       初始化所有位都为0    
           
    bitset(unsigned long val);   

       用unsigned long初始化bitset对象,初始化bitset对象为val的位模式。
           如果bitset对象的长度小于val的位数,那么val中多余的高位被丢弃;
           如果bitset对象的长度大于val的位数,那么bitset对象的高位将被置为0    

    explicit bitset(const string& str, size_t pos = 0, size_t n = -1);

       用string对象中从pos下标开始的n个字符来初始化bitset对象(这些字符必须是0或者1)。如果str.size() < pos,那么将抛出out_of_range异常。如果指定的字符序列[pos, pos + n)中有非0、1字符,那么将抛出invalid_argument异常。如果n > str.size() - pos,就只使用str.size() - pos位来初始化bitset对象。如果指定的字符序列中字符个数比bitset对象位数要多,则只使用前面的字符。

       初始化规则:[pos, pos + n)序列中最后一个字符对应着bitset对象的低位(第一位),而第一个字符对应着高位。(这点符合我们看待字符串形式的位串的方式:左边是高位,右边是低位)


    举例:
    bitset<16> bs1;                   // bs1有16位,并全部初始化为0

    bitset<16> bs2(0xFFFF);           // bs2有16位,并全部初始化为1
    bitset<32> bs3(0xFFFF);           // bs3有32位,低16位(0-15)为1,高16位(16-31)为0
    bitset<8>  bs4(0xFFFF);           // bs4有8位,并全部初始化为1

    string test("111110000011");
    bitset<8> bs5(test);              // bs5有8位,并且只使用test串的前八个字符"11111000"来初始化,
                                      //   所以0-7位为:0001 1111(注意与源串反向)
    bitset<8> bs6(test, 4, 3);        // bs6有8位,并且用"100"来初始化,所以0-7位为:0010 0000

    位的测试

    bool any() const;                 // 如果容器内有任意位被置为1,则返回true;否则返回false。
    bool none() const;                // 如果容器内没有位被置为1,则返回true;否则返回false。
    bool test(size_t pos, bool val = true);      // 测试位置pos处的位是否为val(默认测试是否为1)
                                                 // 如果pos >= size(),那么将抛出异常out_of_range

    bool at(size_type pos) const;     // 返回指定位;如果pos无效,那么将抛出异常out_of_range。
    reference at(size_type pos);
    bool operator[](size_type pos) const;
    reference operator(size_type pos);


    static const size_t bitset_size = N; //容器内的位个数N
    size_t size() const;              // 返回容器内的位个数N
    size_t count() const;             // 返回被置为1的位的个数

    bitset<N>& flip();                // 将容器内所有位全部取反
    bitset<N> operator~();            // 返回this->flip();
    bitset<N>& flip(size_t pos);      // 将位置pos处的位取反;如果pos >= size(),那么将抛出异常out_of_range。

    bitset<N>& reset();               // 将容器内所有位重置为0
    bitset<N>& reset(size_t pos);     // 将位置pos处的位置为0;如果pos >= size(),那么将抛出异常out_of_range
    bitset<N>& set();                 // 将容器内所有位重置为1
    bitset<N>& set(size_t pos, bool val = true); // 将位置pos处的位置为val(默认为1);
                                                 // 如果pos >= size(),那么将抛出异常out_of_range


    unsigned long to_ulong() const;   // 返回对应的unsigned long值;如果溢出,则抛出overflow_error
    string to_string() const;         // 把bitset对象转换成string对象,其规则是:字符串的第一字符对应容器中最后一位。
            
    bool operator ==(const bitset<N>& rhs) const;   // 如果两容器的位序列完全相等,则返回true;否则返回false.
    bool operator !=(const bitset<N>& rhs) const;   // 如果两容器的位序列不完全相等,则返回true;否则返回false。

    bitset<N>& operator&=(const bitset<N>& rhs);    // 位串进行“与”运算
    bitset<N>& operator|=(const bitset<N>& rhs);    // “或”运算
    bitset<N>& operator^=(const bitset<N>& rhs);

    bitset<N>& operator<<=(size_t pos);          // 逻辑左移pos位(向高位方向移动)
    bitset<N>& operator>>=(size_t pos);          // 逻辑右移pos位(向低位方向移动)
    bitset<N> operator<<(size_t pos) const;      // 返回 bitset<N>(*this) <<= pos.
    bitset<N> operator>>(size_t pos) const;      // 返回 bitset<N>(*this) >>= pos.

    非成员函数
    ostream& operator<<(ostream& os, const bitset<N>& x);
       相当于调用return os<<x.to_string();
    istream& operator>>(istream& is, bitset<N>& x);
       相当于调用: string str; is>>str; x = bitset<N>(str); return is;
          其中,当从输入流is提取的字符个数已经有N个时,提取结束;当遇到文件尾时,提取结束;当is中当前字符不是0也不是1时,提取结束。
       如果没有提取到任何字符就结束了(此时x不变),那么将调用is.setstate(ios_base::failbit)。

    bitset<N> operator&(const bitset<N>& lhs, const bitset<N>& rhs);    // 返回 bitset<N>(lhs) &= rhs.
    bitset<N> operator|(const bitset<N>& lhs, const bitset<N>& rhs);    // 返回 bitset<N>(lhs) |= rhs.
    bitset<N> operator^(const bitset<N>& lhs, const bitset<N>& rhs);    // 返回 bitset<N>(lhs) ^= rhs.

    另外, bitset中的reference定义如下:
    class reference {
    public:
        reference& operator=(bool b};
        reference& operator=(const reference& x);
        bool operator~() const;
        operator bool() const;
        reference& flip();
    };

    其使用举例如下:
    bitset<8> bs(string("111110000011"));
    bs[2] = 0;           // 此时bs[0]-bs[7]为00011011
    bool b = ~x[2];      // b == 1, bs不变
    x[2].flip();         // bs改变:bs[0]-bs[7]为00011111

    应用示例

    #include <iostream>
    #include <cassert>
    #include <bitset>

    using namespace std;

    int main()
    {
        bitset<16> bs1; // bs1有16位,并全部初始化为0

        assert(bs1.none());
        bitset<16> bs2(0xFFFF); // bs2有16位,并全部初始化为1

        assert(bs2.count() == 16);
        bitset<32> bs3(0xFFFF); // bs3有32位,低16位(0-15)为1,高16位(16-31)为0

        assert(bs3.to_ulong() == 0xFFFF);
        bitset<8> bs4(0xFFFF); // bs4有8位,并全部初始化为1

        assert(bs4.count() == 8);
        string test("111110000011");
        bitset<8> bs5(test); // bs5有8位,并且只使用test串的前八个字符"11111000"来初始化,

                                          // 所以0-7位为:0001 1111(注意与源串反向)

        assert(bs5.to_ulong() == 0xF8);
        bitset<8> bs6(test, 4, 3); // bs6有8位,并且用"100"来初始化,所以0-7位为:0010 0000

        assert(bs6.to_ulong() == 0x04);
        
        assert((bs5 & bs6) == bitset<8>());
        assert((bs5 | bs6) == bitset<8>(string("11111100")));
        assert((bs5 ^ bs6) == bitset<8>(string("11111100")));
        
        bs5[1] = 1; // 此时bs[0]-bs[7]为01011111

        assert(bs5.to_ulong() == 0xFA);
        bool b = ~bs5[1]; // b == 0, bs不变

        assert(!b);
        assert(bs5.to_ulong() == 0xFA);
        bs5[1].flip(); // bs改变:bs[0]-bs[7]为00011111

        assert(bs5.to_ulong() == 0xF8);
        
        assert((bs5 << 4) == bitset<8>(string("10000000")));
        bitset<8> bs7(bs5);
        bs7 >>= 4;
        assert(bs7 == bitset<8>(string("00001111")));    
        
        bitset<16> bs8;
        cout<<"Before input: "<<bs8<<endl;
        cout<<"Please input: "<<endl;
        cin>>bs8;
        cout<<"After input: "<<bs8<<endl;

        cout<<"OK! All tests passed."<<endl;
        
        return 0;
    }

    转载自:http://blog.chinaunix.net/u/18517/showart_232126.html

  • 相关阅读:
    怎么查看京东店铺的品牌ID
    PPT编辑的时候很卡,放映的时候不卡,咋回事?
    codevs 1702素数判定2
    codevs 2530大质数
    codevs 1488GangGang的烦恼
    codevs 2851 菜菜买气球
    hdu 5653 Bomber Man wants to bomb an Array
    poj 3661 Running
    poj 1651 Multiplication Puzzle
    hdu 2476 String Painter
  • 原文地址:https://www.cnblogs.com/sql4me/p/1661649.html
Copyright © 2011-2022 走看看