概述

C++内置的数组支持容器的机制,但是它不支持容器抽象的语义。要解决此问题我们自己实现这样的类。在标准C++中,用容器向量(vector)实现。

容器向量也是一个类模板。vector是C++标准模板库中的部分内容,它是一个多功能的,能够操作多种数据结构和算法的模板类和函数库。vector之所以被认为是一个容器,是因为它能够像容器一样存放各种类型的对象,但是一个容器中的对象必须是同一种类型。简单地说,vector是一个能够存放任意类型的动态数组,能够增加和压缩数据

vector是一个类模板,不是一种数据类型。可用来定义任意多种数据类型。vector类型的每一种都指定了其保存元素的类型。因此vector <int >等都是数据类型。

vector对象初始化

vector 类定义了好几种构 造函数,用来定义和初始化 vector 对象。

初始化 vector 对象的方式

vector <T >  v1 ;

vector 保存类型为 T 的对象。默认构造函数 v1 为空。

vector < T > v2 ( v1 );

v2 是 v1 的一个副本。

vector < T > v3 ( n , i );

v3 包含 n 个值为 i 的元素。

vector < T > v4 ( n );

v4 含有值初始化的元素的 n 个副本。

创建确定个数的元素

若要创建非空的 vector 对象,必须给出初始化元素的值。当把一个 vector 对象复制到另一个 vector 对象时,新复制的 vector 中每一个元素都初始化为原 vector 中相应元素的副本。但这两个 vector 对象必须保存同一种元素类型:

vector<int> ivec1;                // ivec1 holds objects of type int

vector<int> ivec2(ivec1);       // ok: copy elements of ivec1 into ivec2

vector<string> svec(ivec1);    // error: svec holds strings, not ints

可以用元素个数和元素值对 vector 对象进行初始化。构造函数用元素个数来决定 vector 对象保存元素的个数,元素值指定每个元素的初始值:

vector<int> ivec4(10, -1);           // 10 elements, each initialized to -1

vector<string> svec(10, "hi!");   // 10 strings, each initialized to "hi!"

值初始化

如果没有给出元素的初始化式,那么标准库将提供一个 值初始化的 ( value initialized )元素初始化式。这个由库生成的初始值用于初始化容器中的每个元素。而元素初始化式的值取决于存储在 vector 中元素的数据类型。

如果 vector 保存内置类型(如 int 类型) 的元素,那么标准库将用 0 值创建元素初始 化值:

vector<string> fvec(10); // 10 elements, each initialized to 0

如果向量保存类类型(如 string )的元素,标准库将用该类型的默认构造函数 创建 元素初始值:

vector<string> svec(10); // 10 elements, each an empty string

vector对象操作

vector 基本操作

v. empty()

如果 v 为空,则返回 true, 否则返回 false 。

v . size ()

返回 v 中元素的个数。

v . push _ back ( t )

在 v 的末尾增加一个值为 t 的元素。

v [ n ]

返回 v 中位置为 n 的元素。

v1 = v2

把 v1 的元素替换为 v2 中元素的副本。

v1 == v2

如果 v1 与 v2 相等,则返回 true 。

!=, <, <=, >, >=

保持这些操作符惯有的含义。

vector 对象的 size

empty 和 size 操作类似于 string 类型的相关操作。成员函数 size 返回相应 vector 类定义的size_type 的值。

使用 size_type 类型时,必须指出该类型是在哪里定义的。 vector 类型总是 包括 vector 的元素类型:

vector<int>::size_type        // ok

vector::size_type          // error

向 vector 添加元素

push_back() 操作接受一个元素值,并将它作为一个新的元素添加到 vector 对象的后面,也就是“ 插入 ( push)” 到 vector 对象的 “ 后面 ( back ) ” :

[cpp] view plain copy

 

  1. <span style="font-weight:normal;"><span style="font-size:14px;">// read words from the standard input and store them as elements in a vector
  2. string word;
  3. vector<string> text;        // empty vector
  4. while (cin >> word) {
  5. text.push_back(word);  // append word to text
  6. }</span></span>

该循环从标准输入读取一系列 string 对象,逐一追加到 vector 对象的后面。首先定义一个空的 vector 对象 text 。每循环一次就添加一个新元素到 vector 对象,并将从 输入 读取的 word 值赋予该元素。当循环结束时, text 就包含了所有读入的元素。

vector 的下标操作(更推荐用迭代器)

vector 中的对象是没有命名的,可以按 vector 中对象的位置来访问它们。通常使用下标操作符来获取元素。 vector的下标操作类似于 string 类型的下标操作 ( 3 .2 .3 节 ) 。

vector 的下标操作符接受一个值,并返回 vector 中该对应位置的元素。 vector 元素的位置从 0 开始。下例使用 for循环把 vector 中的每个元素值都重置为 0 :

[cpp] view plain copy

 

  1. <span style="font-weight:normal;"><span style="font-size:14px;">// reset the elements in the vector to zero
  2. for (vector<int>::size_type ix = 0; ix != ivec.size(); ++ix)
  3. ivec[ix] = 0;</span></span>

和 string 类型的下标操作符一样, vector 下标操作的结果为左值,因此可以像循环体中所做的那样实现写入。另外,和 string 对象的下标操作类似,这里用 size_type 类型作为 vector 下标的类型。

在上例中,即使 ivec 为空, for 循环也会正确执行。 ivec 为空则调用 size 返回 0 ,并且 for 中的测试比较 ix 和 0 。第一次循环时,由于 ix 本身就是 0 ,则条件测试失败, for 循环体一次也不执行。

仅能对确知已存在的元素进行下标操作          

初学 C ++ 的程序员可能会认为 vector 的下标操作可以添加元素,其实不然:

[cpp] view plain copy

 

  1. vector<int> ivec;   // empty vector
  2. for (vector<int>::size_type ix = 0; ix != 10; ++ix)
  3. ivec[ix] = ix; <span style="color:#ff0000;"><strong>// disaster: ivec has no elements</strong></span>

上述程序试图在 ivec 中插入 10 个新元素,元素值依次为 0 到 9 的整数。但是,这里 ivec 是空的 vector 对象,而且下标只能用于获取已存在的元素。

这个循环的正确写法应该是:

[cpp] view plain copy

 

  1. for (vector<int>::size_type ix = 0; ix != 10; ++ix)
  2. ivec.push_back(ix);  // ok: adds new element with value ix<span style="color:#000000;font-family:Arial;"> </span>

 必须是已存在的元素才能用下标操作符进行索引。通过下标操作进行赋值时,不会添加任何元素。

 
   

对于下标操作符 ( [] 操作符 ) 的使用有一点非常重要,就是仅能提取确实已存在的元素,例如:

[cpp] view plain copy

 

  1. vector<int> ivec;      // empty vector
  2. cout << ivec[0];        // Error: ivec has no elements!
  3. vector<int> ivec2(10); // vector with 10 elements
  4. cout << ivec[10];      // Error: ivec has elements 0...9

试图获取不存在的元素必然产生运行时错误。和大多数同类错误一样,不能确保执行过程可以捕捉到这类错误,运行程序的结果是不确定的。由于取不存在的元素的结果是未定义的,因而不同的实现会导致不同的结果,但程序运行时几乎肯定会以某种有趣的方式失败。

本警告适用于任何使用下标操作的时候,如 string 类型的下标操作,以及将要简要介绍的内置数组的下标操作。

不幸的是,试图对不存在的元素进行下标操作是程序设计过程中经常会犯的严重错误。所谓的“缓冲区溢出”错误就是对不存在的元素进行下标操作的结果。这样的缺陷往往导致 PC 机和其他应用中最常见的安全问题。

其他以及迭代器

① v.resize(2*v.size)或v.resize(2*v.size, 99) 将v的容量翻倍(并把新元素的值初始化为99)

②使用迭代器访问元素.

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

[cpp] view plain copy

 

[cpp] view plain copy

 

  1. c.insert(pos,elem) // 在pos位置插入一个elem拷贝,传回新数据位置。
  2. c.insert(pos,n,elem) // 在pos位置插入n个elem数据。无返回值。
  3. c.insert(pos,beg,end) // 在pos位置插入在[beg,end)区间的数据。无返回值。

vec.insert(vec.begin()+i,a);    在第i+1个元素前面插入a;

c.erase(pos)          删除pos位置的数据,传回下一个数据的位置。

c.erase(beg,end)    删除[beg,end)区间的数据,传回下一个数据的位置。

c.assign(beg,end)   将[beg; end)区间中的数据赋值给c

c.assign(n,elem)     将n个elem的拷贝赋值给c。

⑥  c.at(idx)        传回索引idx所指的数据,如果idx越界,抛出out_of_range。

⑦c.back()  传回最后一个数据,不检查这个数据是否存在。

⑧   c.begin()传回迭代器中的第一个数据

  c.clear()移除容器中所有数据。

  c.empty()判断容器是否为空。

  c.end()指向迭代器中末端元素的下一个,指向一个不存在元素。

其他更多参见百科:http://baike.baidu.com/link?url=L6vhhZKTvp6C62nPFPbYKnxbqXnRUTwt-2dV7e07ACU0CnFJ6kbyDbwQ-iPGqoY_

More:vector结构体

vector的元素不仅仅可以使int,double,string,还可以是结构体,但是要注意:结构体要定义为全局的,否则会出错。下面是一段简短的程序代码:

[cpp] view plain copy

 

  1. #include<stdio.h>
  2. #include<algorithm>
  3. #include<vector>
  4. #include<iostream>
  5. using namespace std;
  6. typedef struct rect
  7. {
  8. int id;
  9. int length;
  10. int width;
  11.   //对于向量元素是结构体的,可在结构体内部定义比较函数,下面按照id,length,width升序排序。
  12.   bool operator< (const rect &a)  const
  13. {
  14. if(id!=a.id)
  15. return id<a.id;
  16. else
  17. {
  18. if(length!=a.length)
  19. return length<a.length;
  20. else
  21. return width<a.width;
  22. }
  23. }
  24. }Rect;
  25. int main()
  26. {
  27. vector<Rect> vec;
  28. Rect rect;
  29. rect.id=1;
  30. rect.length=2;
  31. rect.width=3;
  32. vec.push_back(rect);
  33. vector<Rect>::iterator it=vec.begin();
  34. cout<<(*it).id<<' '<<(*it).length<<' '<<(*it).width<<endl;
  35. return 0;
  36. }

算法:

 #include<algorithm>中的泛函算法
搜索算法:find() 、search() 、count() 、find_if() 、search_if() 、count_if() 
分类排序:sort() 、merge() 
删除算法:unique() 、remove() 
生成和变异:generate() 、fill() 、transformation() 、copy() 
关系算法:equal() 、min() 、max() 
sort(v1.begin(),vi.begin()+v1.size/2); 对v1的前半段元素排序
list<char>::iterator pMiddle =find(cList.begin(),cList.end(),'A');找到则返回被查内容第一次出现处指针,否则返回end()。
vector< typeName >::size_type x ; vector< typeName >类型的计数,可用于循环如同for(int i)

使用reverse将元素翻转

reverse(vec.begin(),vec.end());将元素翻转(在vector中,如果一个函数中需要两个迭代器,

一般后一个都不包含.)

使用sort排序

sort(vec.begin(),vec.end());(默认是按升序排列,即从小到大).

可以通过重写排序比较函数按照降序比较,如下:

定义排序比较函数:

[cpp] view plain copy

 

  1. bool Comp(const int &a,const int &b)
  2. {
  3. return a>b;
  4. }

调用时:sort(vec.begin(),vec.end(),Comp),这样就降序排序。

[cpp] view plain copy

 

  1. /*
  2. vector 综合练习
  3. Written by C_SuooL_Hu
  4. 2013 10 29
  5. */
  6. #include <vector>
  7. #include <string>
  8. #include <iostream>
  9. #include <algorithm>
  10. using namespace std ;
  11. int main()
  12. {
  13. // 四种初始化方式
  14. vector<int> ivec_1;
  15. vector<int> ivec_2(ivec_1);
  16. vector<int> ivec_3(10, 0) ;
  17. vector<int> ivec(10);
  18. // 定义迭代器变量
  19. vector<int>::iterator iter;
  20. // 定义下标变量
  21. vector<int>::size_type ix ;
  22. system("echo off");
  23. system("color 3") ;
  24. // reset all the elements in ivec to 0
  25. // 使用下标操作,重置为1
  26. for (ix = 0; ix != ivec.size(); ++ix)
  27. ivec[ix] = 1;
  28. // print what we've got so far: should print 10 0's
  29. cout << "使用下标赋值为1的vector<int>类型(同样用下标遍历输出):"<< endl;
  30. for (ix = 0; ix != ivec.size(); ++ix)
  31. cout << ivec[ix] << " ";
  32. cout << endl;
  33. // 使用迭代器的操作赋值,重置为0
  34. for (iter = ivec.begin(); iter !=ivec.end(); ++iter )
  35. *iter = 0;
  36. // 遍历输出,使用迭代器
  37. cout<<"使用迭代器赋值为0的vector<int>类型(同样用迭代器遍历输出):" << endl;
  38. for (iter = ivec.begin(); iter !=ivec.end(); ++iter )
  39. cout<< *iter << ' ' ;
  40. cout<< endl ;
  41. iter = ivec.begin();
  42. while (iter != ivec.end())
  43. {
  44. *iter =2 ;
  45. ++iter;
  46. }
  47. // 遍历输出,使用迭代器
  48. cout<<"使用while循环的迭代器赋值为2的数列的vector<int>类型(同样用迭代器遍历输出):" << endl;
  49. for (iter = ivec.begin(); iter !=ivec.end(); ++iter )
  50. cout<< *iter << ' ' ;
  51. cout<< endl << endl ;
  52. // 使用vector的成员函数操作vector<int>类型数据
  53. // 添加元素
  54. cout << "使用vector的成员函数操作vector<int>类型数据" << endl;
  55. cout << "添加元素" << endl ;
  56. cout << "使用迭代器,添加九个递增元素" << endl ;
  57. for (ix = 0; ix != 10; ++ ix)
  58. ivec.push_back(ix);
  59. cout << "此时ivec共有" << ivec.size() << "个元素"<< endl;
  60. // 遍历输出,使用迭代器
  61. cout<<"使用下标增加元素为递增的的数列的vector<int>类型(同样用迭代器遍历输出):" << endl;
  62. for (iter = ivec.begin(); iter !=ivec.end(); ++iter )
  63. cout<< *iter << ' ' ;
  64. cout<< endl << endl;
  65. // 插入元素
  66. cout << "插入元素:在第二个位置插入一个43" << endl ;
  67. ivec.insert(ivec.begin() + 1, 43);   // 在2位置插入一个43拷贝,传回新数据位置。
  68. // 遍历输出,使用迭代器
  69. cout<<"使用迭代器遍历输出:" << endl;
  70. for (iter = ivec.begin(); iter !=ivec.end(); ++iter )
  71. cout<< *iter << ' ' ;
  72. cout << "\n此时ivec共有" << ivec.size() << "个元素"  ;
  73. cout<< endl << endl ;
  74. cout << "插入元素:在第一个位置插入三个13" << endl ;
  75. ivec.insert(ivec.begin(), 3 , 13);  // 在1位置插入3个13数据。无返回值。
  76. // 遍历输出,使用迭代器
  77. cout<<"使用迭代器遍历输出:" << endl;
  78. for (iter = ivec.begin(); iter !=ivec.end(); ++iter )
  79. cout<< *iter << ' ' ;
  80. cout << "\n此时ivec共有" << ivec.size() << "个元素";
  81. cout<< endl << endl ;
  82. cout << "插入元素:在第7个位置插入ivec的[1, 6) 之间的数据:" << endl ;
  83. ivec.insert(ivec.begin()+6, ivec.begin(), ivec.begin()+5); // 在7位置插入在[10,19)区间的数据。无返回
  84. // 遍历输出,使用迭代器
  85. cout<<"使用迭代器遍历输出:" << endl;
  86. for (iter = ivec.begin(); iter !=ivec.end(); ++iter )
  87. cout<< *iter << ' ' ;
  88. cout << "\n此时ivec共有" << ivec.size() << "个元素";
  89. cout<< endl << endl ;
  90. cout << "使用assign赋值ivec_1(将ivec的第[10,19)个元素赋值给他):" <<endl ;
  91. ivec_1.assign(ivec.begin()+9, ivec.begin()+18);
  92. cout<<"使用迭代器遍历输出:" << endl;
  93. for (iter = ivec_1.begin(); iter !=ivec_1.end(); ++iter )
  94. cout<< *iter << ' ' ;
  95. cout << "\n此时ivec_1共有" << ivec_1.size() << "个元素";
  96. cout << endl;
  97. cout << "使用assign赋值ivec_2:" <<endl ;
  98. ivec_2.assign(10,8) ;
  99. cout<<"使用迭代器遍历输出:" << endl;
  100. for (iter = ivec_2.begin(); iter !=ivec_2.end(); ++iter )
  101. cout<< *iter << ' ' ;
  102. cout << "\n此时ivec_2共有" << ivec_2.size() << "个元素";
  103. cout << endl;
  104. // 元素排序
  105. /*
  106. 由于vc 6.0对模板库支持不够好,这里的排序函数无法通过编译,但是使用vs2010编译通过。
  107. cout << "对ivec排序:" << endl;
  108. bool Comp(const int &a,const int &b)
  109. {
  110. return a>b;
  111. }
  112. sort (ivec.begin(), ivec.end,Comp);
  113. cout<<"从大到小排序后,使用迭代器遍历输出:" << endl;
  114. for (iter = ivec_2.begin(); iter !=ivec_2.end(); ++iter )
  115. cout<< *iter << ' ' ;
  116. */
  117. cout << "是否为空(0代表不是,1代表是):" << ivec.empty() << endl;
  118. ivec.clear() ;
  119. cout << "清空元素" << endl;
  120. cout << "是否为空:"  << ivec.empty() << endl;
  121. return 0;
  122. }

运行结果:

 
 
 

转载于:https://www.cnblogs.com/byteHuang/p/8168675.html

C++ vector类型要点总结(以及各种algorithm算法函数)相关推荐

  1. Th2.8:vector类型详述

    本博客将记录:vector类型这个知识点的笔记!     今天总结的知识分为3个点:    一.vector类型简介    二.定义和初始化vector对象(只介绍日常coding中最常用的几种)   ...

  2. C++笔记之结构体内对vector初始化,一般初始化,和类内私有vector类型成员变量初始化

    C++笔记之结构体内对vector初始化,一般初始化,和类内私有vector类型成员变量初始化 文章目录 C++笔记之结构体内对vector初始化,一般初始化,和类内私有vector类型成员变量初始化 ...

  3. CTF逆向-[b01lers2020]little_engine-cpp基本函数用法和byte类型要点

    CTF逆向-[b01lers2020]little_engine-cpp基本函数用法和byte类型要点 来源:https://buuoj.cn/ 内容: 附件:https://pan.baidu.co ...

  4. OpenCV-细化算法(thinning algorithm)算法详解——提取二值图的骨架

    昨天不是说同学问我怎么绘制出轮廓的中心线.然后我上网查了一下其实这个有专门的算法叫做细化算法.用专业术语去描述绘制出轮廓的中心线叫做(提取图像的骨架).然后这一篇博客呢是我对这个细化算法的解读与实操~ ...

  5. Algorithm(算法

    作者:starfish starfish@vip.sina.com 算法是在有限步骤内求解某一问题所使用的一组定义明确的规则.通俗点说,就是计算机解题的过程.在这个过程中,无论是形成解题思路还是编写程 ...

  6. C++11-列表初始化/变量类型推导/范围for/finaloverride/默认成员函数控制

    C++11-列表初始化/变量类型推导/范围for/final&override/默认成员函数控制 零.前言 一.C++11简介 二.列表初始化 1.内置类型列表初始化 2.自定义类型列表初始化 ...

  7. 子图同构问题与Ullmann Algorithm 算法(一)

    目录索引 目录索引 写在前面的话 子图同构定义 子图同构的映射关系 Reference 写在后面的话 写在前面的话 谨以此片献给 my best love, grandpa. 时光匆匆流逝,我们永远无 ...

  8. #include algorithm 常用函数

    #include <algorithm> 常用函数   accumlate : iterator 对标志的序列中的元素之和,加到一个由 init 指定的初始值上.重载的版本不再做加法,而是 ...

  9. jQuery $.post()返回类型为json时不进入回调函数的原因及解决方法

    jQuery $.post()返回类型为json时不进入回调函数的原因及解决方法 参考文章: (1)jQuery $.post()返回类型为json时不进入回调函数的原因及解决方法 (2)https: ...

最新文章

  1. Jmeter之后置处理器操作
  2. ic读卡器设置工具_IC设计工程师的职业前景真的有别人说的那么好吗?
  3. java 中的 super
  4. 复杂网络表示的原理,算法和应用
  5. 基于springboot2.x集成缓存注解及设置过期时间
  6. 微软MCP之SharePoint2007考试试题(Microsoft 70-542)
  7. Scala学习笔记04:内建控制结构
  8. jsp页面播放服务器视频
  9. 【健康管理系统——开题报告 分享(仅供参考呀)】
  10. 百科不全书之Python进阶
  11. 群晖-VideoStation-(TMDB刮削器)api申请
  12. matlab车标识别,MATLAB车辆标识识别技术研究
  13. 掌阅科技让数字化阅读更便捷
  14. 使用python异步框架aiohttp从NASA抓取火星图片
  15. 抖音主页位置怎么自己创建服务器,抖音个人主页在哪?怎么设置?
  16. 微信公众号:支付宝支付
  17. 华为云设计语言_让开发者相见恨晚?!华为云软件开发云实现云上敏捷开发
  18. 人工智能数学课高等数学线性微积分数学教程笔记(3. 线性代数基础)
  19. 阿里云AI训练营-SQL基础3:复杂查询方法-视图、子查询、函数等
  20. element table 展开行 自定义展开方式与触发方式

热门文章

  1. 学计算机还要写作文吗,第一次学电脑作文3篇
  2. python 分类_Python数据类型分类
  3. 写出记录型信号量中的wait操作代码_操作系统进程的同步与互斥及经典同步与互斥问题...
  4. mac 安装laravel Valet环境
  5. 显示和隐藏菜单栏(两种方式div、table)
  6. 线程协作-CountDownLatch
  7. 如何创建 SVN 服务器,并搭建自己的 SVN 仓库
  8. eclipse工具栏sdk和avd图标
  9. 笔试 - 高德软件有限公司python问题 和 答案
  10. iphone 流媒体