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

概述

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

时间: 2024-10-28 20:28:01

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

C++ Primer 学习笔记_7_标准库类型(续1) -- vector类型

 标准库类型(二) --vector类型 引子: vector是同一种类型的对象的集合,每个对象都有一个对应的整数索引值.和string对象一样,标准库将负责管理与存储元素相关的内存. 我们将vector称之为容器,一个容器中的所有对象都必须是同一类型的! [cpp] view plaincopyprint? #include <vector> using std::vector; #include <vector> using std::vector; [模板] vector

Spark DataFrame vector 类型存储到Hive表

1. 软件版本 软件 版本 Spark 1.6.0 Hive 1.2.1 2. 场景描述 在使用Spark时,有时需要存储DataFrame数据到Hive表中,一般的存储方式如下: // 注册临时表 myDf.registerTempTable("t1") // 使用SQLContext从临时表创建Hive表 sqlContext.sql("create table h1 as select * from t1") 在DataFrame中存储一般的数据类型,比如Do

C++ 标准库类型之vector类型

vector是同一种类型的对象的集合,每个对象都有一个对应的证书索引值.和string对象一样,标准库将负责管理与存储元素相关的内存,我们把vector称为容器,因为他可以包含其他对象.一个容器中的所有对象必须是同一种类型 使用vector之前,必须包含相应的头文件. vector是一个类模板(class template)使用模板可以编写一个类定义或函数定义,而用于多个不同数据类型.因此 我们可以定义保存string对象的vector,或保存int值得vector 又或是保存自定义的类类型对象

【C/C++学院】0825-类模板/final_override/类模板与普通类的派生类模板虚函数抽象模板类/类模板友元/位运算算法以及类声明/Rtti 实时类型检测/高级new创建/类以及函数包装器

类模板 类模板多个类型默认类型简单数组模板 #pragma once template <class T=int>//类模板可以有一个默认的值 class myArray { public: myArray(); ~myArray(); }; #include "myArray.h" template <class T=int>//每一个函数都需要加上一个默认的值 myArray<T>::myArray() //类模板成员函数在外部,需要加载类型初始

#include &lt;algorithm&gt; 常用函数

#include <algorithm> 常用函数 accumlate : iterator 对标志的序列中的元素之和,加到一个由 init 指定的初始值上.重载的版本不再做加法,而是传进来的二元操作符被应用到元素上. adjacent_different :创建一个新序列,该序列的每个新值都代表了当前元素与上一个元素的差.重载版本用指定的二元操作计算相邻元素的差. adjacent_find :在 iterator 对标志的元素范围内,查找一对相邻的重复元素,如果找到返回一个 Forward

PHP中文件类型 文件属性 路径以及 文件相关的函数

一: 文件类型判断: 1.is_dir()  判断是不是目录 2.is_file() 判断是不是文件 3.is_executeable() 判断是不是可执行文件 4.is_readable()  判断是不是可读文件 5.is_writable() 判断是不是可写文件 6.is_link()  判断是不是快捷方式 二:文件属性: 1.file_exits()  文件是否存在 2.filesize() 文件大小 3.filectime()  文件创建时间 4.filemtime() 文件修改的时间

C++标准库vector类型的使用和操作总结

vector是一种类型对象的集合,它是一种顺序容器,容器中的所有对象必须都是同一种类型.vector的对象是可以动态生长的,这说明它在初始化时可以不用指定大小,而是再使用时根据元素所需的空间动态增长.C++中还有一种常见的类型string,它和vector有很多相似之处,具体可以看<C++标准库string类型的使用和操作总结>这篇博文.下面简单介绍一下vector容器的使用和操作. 一.声明和初始化 使用vector之前必须在程序前的库包含中包含相应的头文件,如下: #include<

C++ STL vector类型

vector容器是一个模板类,可以存放任何类型的对象(但必须是同一类对象).vector对象可以在运行时高效地添加元素,并且vector中元素是连续存储的.注:vector容器内存放的所有对象都是经过初始化的.如果没有指定存储对象的初始值,那么对于内置类型将用0初始化,对于类类型将调用其默认构造函数进行初始化(如果有其它构造函数而没有默认构造函数,那么此时必须提供元素初始值才能放入容器中). vector的构造函数原型: template<typename T> explicit vector

c++ vector使用要点

1.删除元素 std::vector<int>::iterator it = vec.begin()+10; vec.erase(it);