首页 > 代码库 > 0716-----C++Primer听课笔记----------STL之顺序容器、迭代器

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. 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