zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    数学角度看设计模式之观察者模式
    XML、JSON数据结构解析
    [理解ASP.NET Core框架]一个五十行的控制台Web
    .Net Core 学习 (1)
    SqlServer windowss身份登陆和sa身份登陆
    学习51单片机——秒表分享
    C语言中函数声明实现的位置
    java DOM4J 读取XML
    服务器与Linux操作系统基础原理
    Go语言实现数据结构(一)单链表
  • 原文地址:https://www.cnblogs.com/monicalee/p/3849911.html
Copyright © 2011-2022 走看看