C++学习笔记--STL标准模板库的认识与使用--序列式容器--vector(向量)

1、什么是vector?

(1)std::vector 是 STL 提供的 内存连续的、可变长度 的数组(亦称列表)数据结构。能够提供线性复杂度的插入和删除,以及常数复杂度的随机访问。

(2)Vectors 包含着一系列连续存储的元素,其行为和数组类似。访问Vector中的任意元素或从末尾添加元素都可以在常量级时间复杂度内完成,而查找特定值的元素所处的位置或是在Vector中插入元素则是线性时间复杂度

2、为什么要使用 vector?

1、vector 可以动态分配内存

很多时候我们不能提前开好那么大的空间(eg:预处理 1~n 中所有数的约数)。尽管我们能知道数据总量在空间允许的级别,但是单份数据还可能非常大,这种时候我们就需要 vector 来把内存占用量控制在合适的范围内。vector 还支持动态扩容,在内存非常紧张的时候这个特性就能派上用场了。

2、vector 重写了比较运算符及赋值运算符

vector 重载了六个比较运算符,以字典序实现,这使得我们可以方便的判断两个容器是否相等(复杂度与容器大小成线性关系)。例如可以利用 vector<char> 实现字符串比较(当然,还是用 std::string 会更快更方便)。另外 vector 也重载了赋值运算符,使得数组拷贝更加方便。

3、vector 便利的初始化

由于 vector 重载了 = 运算符,所以我们可以方便的初始化。此外从 C++11 起 vector 还支持 列表初始化,例如 vector<int> data {1, 2, 3};

 3、vector 的创建

// 1. 创建空vector; 常数复杂度
vector<int> v0;
// 1+. 这句代码可以使得向vector中插入前3个元素时,保证常数时间复杂度
v0.reserve(3);
// 2. 创建一个初始空间为3的vector,其元素的默认值是0; 线性复杂度
vector<int> v1(3);
// 3. 创建一个初始空间为3的vector,其元素的默认值是2; 线性复杂度
vector<int> v2(3, 2);
// 4. 创建一个初始空间为3的vector,其元素的默认值是1,
// 并且使用v2的空间配置器; 线性复杂度
vector<int> v3(3, 1, v2.get_allocator());
// 5. 创建一个v2的拷贝vector v4, 其内容元素和v2一样; 线性复杂度
vector<int> v4(v2);
// 6. 创建一个v4的拷贝vector v5,其内容是{v4[1], v4[2]}; 线性复杂度
vector<int> v5(v4.begin() + 1, v4.begin() + 3);
// 7. 移动v2到新创建的vector v6,不发生拷贝; 常数复杂度; 需要 C++11
vector<int> v6(std::move(v2));  // 或者 v6 = std::move(v2);

4、元素访问

  1. at()

    v.at(pos) 返回容器中下标为 pos 的引用。如果数组越界抛出 std::out_of_range 类型的异常。

  2. operator[]

    v[pos] 返回容器中下标为 pos 的引用。不执行越界检查。

  3. front()

    v.front() 返回首元素的引用。

  4. back()

    v.back() 返回末尾元素的引用。

  5. data()

    v.data() 返回指向数组第一个元素的指针。

5、迭代器

  1. begin()/cbegin()

    返回指向首元素的迭代器,其中 *begin = front

  2. end()/cend()

    返回指向数组尾端占位符的迭代器,注意是没有元素的。

  3. rbegin()/crbegin()

    返回指向逆向数组的首元素的逆向迭代器,可以理解为正向容器的末元素。

  4. rend()/crend()

    返回指向逆向数组末元素后一位置的迭代器,对应容器首的前一个位置,没有元素。

6、与长度相关

  • empty() 返回一个 bool 值,即 v.begin() == v.end()true 为空,false 为非空。

  • size() 返回容器长度(元素数量),即 std::distance(v.begin(), v.end())

  • resize() 改变 vector 的长度,多退少补。补充元素可以由参数指定。

  • max_size() 返回容器的最大可能长度。

    与容量相关

  • reserve() 使得 vector 预留一定的内存空间,避免不必要的内存拷贝。

  • capacity() 返回容器的容量,即不发生拷贝的情况下容器的长度上限。

  • shrink_to_fit() 使得 vector 的容量与长度一致,多退但不会少。

7、元素增删及修改

  • clear() 清除所有元素
  • insert() 支持在某个迭代器位置插入元素、可以插入多个。复杂度与 pos 距离末尾长度成线性而非常数的
  • erase() 删除某个迭代器或者区间的元素,返回最后被删除的迭代器。复杂度与 insert 一致。
  • push_back() 在末尾插入一个元素,均摊复杂度为 常数,最坏为线性复杂度。
  • pop_back() 删除末尾元素,常数复杂度。
  • swap() 与另一个容器进行交换,此操作是 常数复杂度 而非线性的。

8、代码示例:

#include<iostream>

#include<vector>

using namespace std;

int main()
{
	vector<int> v0;//创建一个v0向量

	v0.reserve(3);//设置v0最小的元素容纳数量

	for(int i = 1; i <= 10; i++)//将1~10的数字填入向量中
		v0.push_back(i);//在v0最后添加一个元素


	cout<<"first element :" << v0.front() << endl;//返回v0第一个元素

	cout<< "last element :" << v0.back()<<endl;//返回v0最后一个元素

	cout << "number of elements:" << v0.size() << endl;

	v0.clear();//清空

	cout<<"Number of elements:" << v0.size() << endl;

	return 0;
}

运行结果:

 3、依次从头删除(迭代器)

#include<iostream>

#include<vector>

using namespace std;

int main()
{
	vector<int> v0;//创建一个v0向量

	for (int i = 1; i <= 10; i++)//将1~10的数字填入向量中
		v0.push_back(i);//在v0最后添加一个元素

	int size = v0.size();//设置v0长度
	
	vector<int>::iterator startIt;

	vector<int>::iterator tempIt;

	for (int i = 0; i < size; i++)
	{
		startIt = v0.begin();

		v0.erase(startIt);

		//Display the vector

		for (tempIt = v0.begin(); tempIt != v0.end(); tempIt++)
		{
			cout << *tempIt;
		}
		cout << endl;
	}

	return 0;
}

程序运行结果:

猜你喜欢

转载自blog.csdn.net/qq_51701007/article/details/121247239