• 顺序容器的操作


    每种容器都提供一组有用的类型定义以及如下操作

    1. 在容器中添加元素
    2. 在容器中删除元素
    3. 设置容器大小
    4. 获取容器内第一个和最后一个元素

    1. 容器定义的类型别名

    逆序迭代器从后向前遍历容器,并翻转某些相关的迭代器操作。如++rverse_iter 相当于指向前一个元素而不是后一个元素
    需要使用容器元素时,用value_type即可,如果要引用,则可以通过reference和const_reference类型实现。在编程泛型时,这些元素相关定义非常有用。

    容器定义的类型别名 说明
    size_type 容器容量 unsigned int型,最大可能容器长度
    iterator 迭代器
    const_iterator 元素的只读迭代器
    reverse_iterator 逆序迭代器
    const_reverse_iterator 只读的元素逆序迭代器
    difference_type 两个迭代器差值 有符号型
    value_type 容器元素类型
    reference 容器元素的引用
    const_reference 常量引用

    2. begin和end成员

    操作 说明
    c.begin() 返回指向容器c的第一个元素的迭代器
    c.end() 返回指向容器c的最后一个元素的下一位置的迭代器
    c.rbegin() 逆序迭代器 c.rbegin()== (--c.end())
    c.rend() (--c.rend())==c.begin()

    迭代器和逆序迭代器参考图

    3. 在顺序容器中添加元素

    所有顺序容器都支持push_back 操作在容器尾部插入一个元素,并使容器长度+1.

    string text_word;
    while(){
     container.push_back(text_word);
    }
    

    关键概念

    容器中添加元素,试讲元素值复制到容器中,类似,使用一段元素初始化容器时,存放的是元素副本。

    容器中添加元素的操作

    操作 说明
    c.push_back(t) 返回void ,在容器尾部插入一个元素,均摊时间复杂度:O(1)
    c.push_front(t) 返回void,在容器c前段插入一个元素,适用deque和list
    c.insert(p,t) 返回指向新插入元素的迭代器位置,在p之前插入,考虑p为end()情况,因此插入都是在p之前插入
    c.insert(p,n,t) 返回void,在p之前重复插入n个t
    c.insert(p,b,e) 返回void,在p之前插入[b,e)范围内的元素

    虽然vector没有push_front 函数,但是用insert(vec.begin(),t)即可实现。
    insert操作时间复杂度与p位置有关,涉及到已有元素的移动,平均时间复杂度是O(n)

    4. 关系操作符

    所有容器都支持用关系操作符来实现两个容器的比较。比较容器必须具有相同容器类型和相同元素类型。
    容器比较是基于容器内元素的比较。因此,容器元素如果不支持某种关系运算符,则该容器也不支持。
    如果c1,c2都是容器,且表达式c1 < c2合法,那么两个容器类型相同,并且元素类型也相同,并且元素支持 < 运算符。

    5. 容器大小操作

    操作 说明
    c.size() 返回c中元素个数
    c.empty() 返回bool判断容器是否空
    c.resize(n) 调整容器大小,使其能容纳n个元素。若n<c.size(),删除多余元素;若n>c.size(),采用值初始化添加的新元素
    c.resize(n,t) 若n>c.size(),用t初始化添加的元素值

    resize操作失效问题

    在vector和deque上操作resize操作可能会使所有的迭代器失效,realloc重新分配
    如果resize压缩了容器,则指向已经删除的元素的迭代器失效

    6. 访问元素

    如果元素非空,那么front返回第一个元素的引用,back返回最后一个元素的引用。

    操作 说明
    c.front() 返回第一个元素引用
    c.back() 返回最后一个元素的引用
    c[n] 只适用于vector和deque,n值编译器不检查
    c.at(n) 只适用vector和的确,n值编译器不检查,会抛出out_of_range运行时错误

    7. 删除元素

    操作 说明
    c.erase(p) 删除迭代器p所指向的元素,返回一个迭代器,指向删除元素后面的元素,如果p指向最后一个元素,则返回容器末尾下一位置
    c.erase(b,e) 删除迭代范围[b,e),返回e位置,如果e本身为容器末尾下一位置,则返回e也为容器末尾下一位置
    c.clear() 删除容器中所有元素,返回void
    c.pop_back() 删除容器c最后一个元素,返回void
    c.pop_front() 删除容器第一个元素,返回void

    注意容器删除操作要检查容器是否为空,以及所给迭代器是否合法,编译器不负责检查。
    pop_front和front操作配套使用,实现以栈方式处理容器。
    pop_front只有deque和list才有的操作,vector没有

    #include <iostream>
    #include <vector>
    #include <list>
    using namespace std;
    #define ArrayLength(X) ((sizeof(X))/(sizeof(X[0])))
    int main()
    {
    	int ia[]={1,2,3,4,5,6,7,8,9,10};
    	vector<int> ivec(ia,ia+ArrayLength(ia));
    	list<int> ilist(ia,ia+ArrayLength(ia));
    	for (vector<int>::const_iterator beg=ivec.begin();beg!=ivec.end();++beg)
    	{
    		cout<<*beg<<" ";
    	}
    	cout<<endl;
    	for (list<int>::const_iterator beg=ilist.begin();beg!=ilist.end();)
    	{
    		//清除list中所有奇数
    		if (*beg & 0x01)
    		{
    			cout<<"清除"<<*beg <<" ";
    			beg = ilist.erase(beg);
    			cout<<"之后 beg指向元素"<<*beg<<endl;
    		}
    		else
    		{
    			++beg;
    		}
    	}
    	cout<<"iList:";
    	for (list<int>::const_iterator beg=ilist.begin();beg!=ilist.end();++beg)
    	{
    		cout<<*beg<<" ";
    	}
    	cout<<endl;
    	cout<<"vector:";
    	for(vector<int>::const_iterator beg=ivec.begin();beg!=ivec.end();)
    	{
    		//清除vector中所有偶数
    		if (*beg & 0x01)
    			++beg;
    		else
    			beg=ivec.erase(beg);
    	}
    	for (vector<int>::const_iterator beg=ivec.begin();beg!=ivec.end();++beg)
    	{
    		cout<<*beg<<" ";
    	}
    	cout<<endl;
    	system("pause");
    	return 0;
    }
    

    8. 赋值与swap

    与赋值相关的操作符都作用于整个容器。除swap操作外,其他操作都可以用erase和insert操作实现。赋值操作符首先删除其左操作数容器内的所有元素,然后将右操作数容器内的所有元素都插入到左边容器

    c1=c2;
    c1.erase(c1.begin(),c1.end());
    c1.insert(c1.begin(),c2.begin(),c2.end());
    

    赋值和assign操作都使左操作数容器的所有迭代器失效。
    swap操作则不会使迭代器失效。完成swap操作后,尽管被交换元素已经存放在另外一个容器,但是迭代器仍然指向相同元素。

    操作 说明
    c1=c2 删除容器c1内元素,将c2内元素复制给c1,c1和c2类型相同(容器类型,元素类型)
    c1.swap(c2) 交换内容:调用完该函数,c1存放的是c2内的元素;c2存放的是c1内的元素。c1和c2必须类型相同。
    c.assign(b,e) 重置c元素,将[b,e)内的元素复制到c,b和e必须是不指向c中元素的迭代器
    c.assign(n,t) 将容器c重置为n个t值

    使用assign

    assign首先删除容器内元素,然后将新元素插入容器。赋值操作符仅适合类型相同(容器类型,元素类型)assign适合容器类型相同/不相同,容器元素类型相同/兼容。如可以通过将char * 类型转换成string类型

    //容器类型不相同,元素类型相同都是int
    ivec.assign(ilist.begin(),ilist.end());
    vector<char *> svec(4,"china tea");
    //访问元素返回引用可以作为左值进行修改
    svec.front()="chinese";
    svec.back()="comedy";
    svec.at(1)="one";
    for (vector<char*>::iterator beg=svec.begin();beg!=svec.end();++beg)
    {
      cout<<*beg<<" ";
    }
    cout<<endl;
    list<string> slist;
    //容器类型不相同,元素类型相互兼容
    slist.assign(svec.begin(),svec.end());
    for (list<string>::iterator beg=slist.begin();beg!=slist.end();++beg)
    {
      cout<<beg->c_str()<<" ";
    }
    cout<<endl;
    //重置元素,和容器初始化相似
    ivec.assign(10,1);
    

    使用swap操作节省删除元素成本

    swap操作实现交换两个容器内所有元素功能。待交换容器必须完全匹配。该操作不会插入或删除任何元素,保证在常量时间内实现交换。由于没有移动任何元素,迭代器不失效。

    vector<string> svec1(10);
    vector<string> svec2(20);
    svec1.swap(svec2);
    

    执行交换后,svec1内有24个string元素,svec2内有10个string元素。如果交换前svec_beg迭代器指向svec1[0],那么交换后svec_beg指向svec2[0](这是同一个元素只是存储在不同容器中了,迭代器并未失效)。swap操作只会交换两个容器内部数据结构,即交换容器中各元素的内存地址,并不是交换各个元素变量所存储的值。

  • 相关阅读:
    MySQL报错【innoDB is limited to rowlogging when transaction isolation level is READ COMMITTED or READ UNCOMMITTED】
    【转】linux下解压命令大全
    java学习笔记
    【转】Linux安装MySQL tar文件
    Android部署及安装
    正则表达式各个符合含义
    [转]Linux下crontab命令的用法
    XTABLE学习笔记
    MySQL的mysqldump工具的基本用法
    java开发注意事项
  • 原文地址:https://www.cnblogs.com/gaochaochao/p/11890694.html
Copyright © 2020-2023  润新知