0716-----C++Primer听课笔记----------STL之顺序容器、迭代器

1. 顺序容器的初始化操作

1.1 顺序容器(vector,list,deque)的五种初始化方法,以 vector 为例。

#include <iostream>
#include <string>
#include <vector>

using namespace std;

int main(int argc, const char *argv[])
{
    //1.定义空数组 然后后面追加
    vector<string> vec1;
    vec1.push_back("beijing");
    vec1.push_back("shanghai");
    vec1.push_back("guangzhou");
    vec1.push_back("shenzhen");

    cout << "1----------------------------" << endl;
    for(vector<string>::iterator it = vec1.begin(); it != vec1.end(); ++it){
        cout << *it << endl;
    }

    //2.定义时指定大小 然后依次赋值

    vector<string> vec2(5);
    for(vector<string>::size_type ix = 0; ix != 5; ix++){
        vec2[ix] = "tencent";
    }

    cout << "2----------------------------" << endl;
    for(vector<string>::iterator it = vec2.begin(); it != vec2.end(); ++it){
        cout << *it << endl;
    }

    //3.定义时指定大小并赋初值

    vector<string> vec3(4, "facebook");

    cout << "3----------------------------" << endl;
    for(vector<string>::iterator it = vec3.begin(); it != vec3.end(); ++it){
        cout << *it << endl;
    }

    //4.用一个容器去初始化另一个容器

    vector<string> vec4(vec1);

    cout << "4----------------------------" << endl;
    for(vector<string>::iterator it = vec4.begin(); it != vec4.end(); ++it){
        cout << *it << endl;
    }

    //5.用一个迭代器的范围去初始化一个容器
    vector<string> vec5(vec1.begin(), vec1.end());

    cout << "5----------------------------" << endl;
    for(vector<string>::iterator it = vec5.begin(); it != vec5.end(); ++it){
        cout << *it << endl;
    }


    return 0;
}

1.2 用迭代器的一段范围去初始化一个容器时,两种容器可以是不同的容器,只要容器元素类型兼容即可(这个兼容的意思有两层,一是容器vec和容器list可以相互转化,二是容器中的类型比如vec<int> 和 vec<double>可以相互转化,总结来说就是, vec<int> 和 list<double> 可以相互转化)。当用一个容器去初始化另一个容器的时候,容器类型和容器内的元素类型 都必须相同

#include <iostream>
#include <string>
#include <vector>
#include <list>
#include <algorithm>

using namespace std;
/*
 *用迭代器的一段范围初始化容器
 *被初始化的容器可以使另一种容器
 */


int main(int argc, const char *argv[])
{
    list<string> lst;
    lst.push_back("apple");
    lst.push_back("google");
    lst.push_back("microsoft");
    lst.push_back("oracle");


    list<string>::iterator res = find(lst.begin(), lst.end(), "google");
    if(res == lst.end()){
        cout << "not found" << endl;
        return -1;
    }

    vector<string> vec(res, lst.end());
    for(vector<string>::iterator it = vec.begin(); it != vec.end(); ++it){
        cout << *it << endl;
    }

    return 0;
}

1.3 vector 和 list 的区别

a) vector 内部采用原生数组实现, list  则是基于链表;

b) vector 支持随机访问,list 只能顺序访问, 不支持下标操作(如下例所示,会出错,提示没有[]操作符)。

#include <iostream>
#include <string>
#include <list>

using namespace std;

int main(int argc, const char *argv[])
{
    list<string> lst;
    lst.push_back("apple");
    lst.push_back("google");
    lst.push_back("microsoft");

    cout << lst[1] << endl;
    return 0;
}
图像 6

1.4 STL中容器内的元素必须支持复制和赋值操作。如下例所示,会出错。这里要注意,push_back实际放入的是元素的副本,所以要求元素必须具有复制的能力。

#include <iostream>
#include <string>
#include <vector>
using namespace std;

/*
 *容器中的元素类型必须支持复制和 赋值操作
 *
 */

class Test{
    Test(){}
    private:
        /*
         *下面第一行用于复制
         *第二行用于赋值
         *这里均设为私有,使得Test失去复制和赋值的能力
         */
        Test(const Test &);
        Test &operator=(const Test &);

};


int main(int argc, const char *argv[])
{
   vector<Test> vec;
   Test t;

   vec.push_back(t); //push_back操作是把对象的副本放进去 而非对象本身

    return 0;
}

2. 迭代器

2.1 顺序容器中 begin 指向第一个元素 ,end 指向最后一个元素的下一个位置, rbegin 指向最后一个元素, rend指向第一个元素的前一个位置。即迭代器有顺序迭代器和逆序迭代器之分,如下例所示。

#include <iostream>
#include <string>
#include <vector>
#include <list>

using namespace std;

int main(int argc, const char *argv[])
{
    list<string> lst;
    lst.push_back("google");
    lst.push_back("oracle");
    lst.push_back("apple");

    for(list<string>::iterator it = lst.begin(); it != lst.end(); ++it){
        cout << *it << endl;
    }

    cout << "-----------" << endl;

    /*
     *逆序迭代器
     */
    for(list<string>::reverse_iterator it = lst.rbegin(); it != lst.rend(); ++it){
        cout << *it << endl;
    }
    return 0;
}

3. 顺序容器的插入和删除操作

3.1  插入操作

3.1.1  insert 是插入到当前迭代器所指向的位置,其他元素依次后移,如下例所示。

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

using namespace std;

int main(int argc, const char *argv[])
{
    vector<string> vec;
    vec.push_back("apple");
    vec.push_back("google");
    vec.push_back("oracle");
    vec.push_back("ebay");


    vector<string>::iterator res = find(vec.begin(), vec.end(), "oracle");
    if(res == vec.end()){
        cout << "not found" << endl;
        return -1;
    }

    vec.insert(res, "facebook");
    for(vector<string>::iterator it = vec.begin(); it != vec.end(); ++it){
        cout << *it << endl;
    }
    return 0;
}

3.1.2  insert (p, n, t);  即insert重载了可以一次插入多个相同对象的的函数。如下例所示。

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

using namespace std;

int main(int argc, const char *argv[])
{
    vector<string> vec;
    vec.push_back("apple");
    vec.push_back("google");
    vec.push_back("microsoft");

    vector<string>::iterator res = find(vec.begin(), vec.end(), "google");
    if(res == vec.end()){
        cout << "not found" << endl;
        return -1;
    }

    vec.insert(res, 3, "jingdong");

    for(vector<string>::iterator it = vec.begin(); it != vec.end(); ++it){
        cout << *it << endl;
    }
    return 0;
}

3.1.3 inset(p, begin, end) ;即insert 可以把一个容器的迭代器指向的一段范围插入到当前容器中,如下。

#include <iostream>
#include <string>
#include <vector>
#include <list>
#include <algorithm>

using namespace std;

int main(int argc, const char *argv[])
{
    vector<string> vec;
    vec.push_back("apple");
    vec.push_back("google");
    vec.push_back("microsoft");

    vector<string>::iterator res = find(vec.begin(), vec.end(), "google");
    if(res == vec.end()){
        cout << "not found" << endl;
        return -1;
    }
    list<string> lst;
    lst.push_back("baidu");
    lst.push_back("tencent");
    lst.push_back("alibaba");
    vec.insert(res, lst.begin(), lst.end());

    for(vector<string>::iterator it = vec.begin(); it != vec.end(); ++it){
        cout << *it << endl;
    }
    return 0;
}

3.1.4 vector 不支持 push_front 操作,list 支持。如下例所示将报错。

#include <iostream>
#include <string>
#include <vector>
using namespace std;

int main(int argc, const char *argv[])
{
    vector<string> vec;
    vec.push_back("baidu");
    vec.push_back("alibaba");
    vec.push_back("tencent");

    vec.push_front("huawei");
    return 0;
}

图像 1

#include <iostream>
#include <string>
#include <vector>
#include <list>
#include <algorithm>

using namespace std;

int main(int argc, const char *argv[])
{
    vector<string> vec;
    vec.push_back("apple");
    vec.push_back("google");
    vec.push_back("microsoft");

    list<string> lst(vec.begin(), vec.end());
    lst.push_front("facebook");

    for(list<string>::iterator it = lst.begin(); it != lst.end(); ++it){
        cout << *it << endl;
    }

    return 0;
}

4. 删除操作

4.1 pop_frontpop_back删除第一个 和最后一个。

#include <iostream>
#include <string>
#include <vector>
#include <list>

using namespace std;
int main(int argc, const char *argv[])
{
    list<string> lst;
    lst.push_back("apple");
    lst.push_back("google");
    lst.push_back("microsoft");
    lst.push_back("oracle");
    lst.push_back("IBM");

    lst.pop_front();
    for(list<string>::iterator it = lst.begin(); it != lst.end(); ++it){
        cout << *it << endl;
    }

    cout << "-------------" << endl;

    lst.pop_back();
    for(list<string>::iterator it = lst.begin(); it != lst.end(); ++it){
        cout << *it << endl;
    }

    return 0;
}

4.2 erase 删除某一迭代器所指向的元素 或者 迭代器 所指向的一段区间。

#include <iostream>
#include <string>
#include <vector>
#include <list>
#include <algorithm>

using namespace std;
int main(int argc, const char *argv[])
{
    list<string> lst;
    lst.push_back("apple");
    lst.push_back("google");
    lst.push_back("microsoft");
    lst.push_back("oracle");
    lst.push_back("IBM");

    list<string>::iterator res = find(lst.begin(), lst.end(), "microsoft");
    if(res == lst.end()){
        cout << " not found" << endl;
        return -1;
    }

    lst.erase(res); 
    // lst.erase(res, lst.end());
    //
    for(list<string>::iterator it = lst.begin(); it != lst.end(); ++it){
        cout << *it << endl;
    }

5.3 在容器中删除元素时,会导致该元素的迭代器失效,所以当使用erase时,应该用迭代器接收返回值。如下就是迭代器失效的例子,程序出错。

#include <iostream>
#include <string>
#include <vector>
using namespace std;
/*
 *erase 删除元素是 该迭代器会失效
 *erase 操作返回下一个元素的迭代器
 */

int main(int argc, const char *argv[])
{
    vector<int> vec;
    vec.push_back(2);
    vec.push_back(4);
    vec.push_back(5);
    vec.push_back(4);


    for(vector<int>::iterator it = vec.begin(); it != vec.end(); ++it){
        if(*it % 2 == 0){
            vec.erase(it);//此时it 指针失效 程序 core dump
                           // 应改为 it = vec.erase(it);
        }
    }

    for(vector<int>::iterator it = vec.begin(); it != vec.end(); ++it){
        cout << *it << endl;
    }
    return 0;
}

5. vector  内存分配策略

5.1 顺序表的两个容量

a) size: 表示当前存储的元素数量;

b) capacity:表示预先分配的可容纳元素的最大数量。

c)我们通常所说的大小是指size,而不是capacity。vector下标的合法范围是0~size()-1。

5.2 在vector中,size 是存储的元素数量,resize 是改变当前存储的元素数量,这两个函数都属于第一种容量。而 capacity表 示 vector  的最大容量,reserve可以改变最大容量。

a) size:教室的当前人数

b) resize:改变当前的人数

c) capacity:教室可容纳的最大人数

d) reserve:改变教室的容纳量

5.3 vector的内存分配策略

a) 定义空数组时,capacity为0,当制定vec大小为n的时候,capacity也为n。

b) 当capacity占满的时候,此时再次放入元素,capacity变为原来的两倍。

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

using namespace std;

int main(int argc, const char *argv[])
{
    vector<int> vec;
    cout << "size = " << vec.size() << " capacity = " << vec.capacity() << endl;

    for(vector<string>::size_type ix = 0; ix != 10; ix++){
        vec.push_back(ix);
    }
    cout << "after push_back  10..." << endl;
    cout << "size = " << vec.size() << " capacity = " << vec.capacity() << endl;

    vec.reserve(30);
    cout << "after reserve 30  ..." << endl;
    cout << "size = " << vec.size() << " capacity = " << vec.capacity() << endl;

    while(vec.size() != vec.capacity()){
        vec.push_back(2);
    }

    cout << "after filling  ..." << endl;
    cout << "size = " << vec.size() << " capacity = " << vec.capacity() << endl;

    vec.push_back(3);
    cout << "after push_back ..." << endl;
    cout << "size = " << vec.size() << " capacity = " << vec.capacity() << endl;

    return 0;
}
图像 2
原文地址:https://www.cnblogs.com/monicalee/p/3849911.html