【C++庖丁解牛】STL之vector容器的介绍及使用 | vector迭代器的使用 | vector空间增长问题


🍁你好,我是 RO-BERRY
📗 致力于C、C++、数据结构、TCP/IP、数据库等等一系列知识
🎄感谢你的陪伴与支持 ,故事既有了开头,就要画上一个完美的句号,让我们一起加油

在这里插入图片描述



1.1 vector的介绍

vector的文档介绍

  1. vector是表示可变大小数组的序列容器。
  2. 就像数组一样,vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问,和数组一样高效。但是又不像数组,它的大小是可以动态改变的,而且它的大小会被容器自动处理。
  3. 本质讲,vector使用动态分配数组来存储它的元素。当新元素插入时候,这个数组需要被重新分配大小为了增加存储空间。其做法是,分配一个新的数组,然后将全部元素移到这个数组。就时间而言,这是一个相对代价高的任务,因为每当一个新的元素加入到容器的时候,vector并不会每次都重新分配大小。
  4. vector分配空间策略:vector会分配一些额外的空间以适应可能的增长,因为存储空间比实际需要的存储空间更大。不同的库采用不同的策略权衡空间的使用和重新分配。但是无论如何,重新分配都应该是对数增长的间隔大小,以至于在末尾插入一个元素的时候是在常数时间的复杂度完成的。
  5. 因此,vector占用了更多的存储空间,为了获得管理存储空间的能力,并且以一种有效的方式动态增长。
  6. 与其它动态序列容器相比(deque, list and forward_list), vector在访问元素的时候更加高效,在末尾添加和删除元素相对高效。对于其它不在末尾的删除和插入操作,效率更低。比起list和forward_list统一的迭代器和引用更好。

可以理解成vector就是一个顺序表,后面跟着的是其存储的数据类型,连续存储的空间
使用STL的三个境界:能用,明理,能扩展 ,那么下面学习vector,我们也是按照这个方法去学习

2 vector的使用

vector学习时一定要学会查看文档:vector的文档介绍,vector在实际中非常的重要,在实际中我们熟悉常见的接口就可以,下面列出了哪些接口是要重点掌握的。

2.1 vector的定义

(constructor)构造函数声明接口说明
vector()(重点)无参构造
vector(size_type n, const value_type& val = value_type())构造并初始化n个val
vector (const vector& x); (重点)拷贝构造
vector (InputIterator first, InputIterator last);使用迭代器进行初始化构造
	// constructors used in the same order as described above:
	vector<int> first;                                 // empty vector of ints
	vector<int> second(4, 100);                        // four ints with value 100
	vector<int> third(second);                         // a copy of second
	vector<int> fourth(second.begin(), second.end());  // iterating through second

	// 下面涉及迭代器初始化的部分,我们学习完迭代器再来看这部分
	// the iterator constructor can also be used to construct from arrays:
	int myints[] = { 16,2,77,29 };
	vector<int> fifth(myints, myints + sizeof(myints) / sizeof(int));

2.2 vector的打印

这部分内容与string相类似,主要分为:

  1. for+operator[]
  2. 迭代器打印
  3. 范围for
void test1()
{
	vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);

	for (size_t i = 0; i < v.size(); i++)
	{
		cout << v[i] << " ";
	}
	cout << endl;

	vector<int>::iterator it1 = v.begin();
	while (it1 != v.end())
	{
		cout << *it1 << " ";
		++it1;
	}
	cout << endl;
	
	for (auto e : v)
	{
		cout << e << " ";
	}
	cout << endl;

}

在这里插入图片描述

2.3 vector<char>与string的区别

我们可以看到vector<char>和string都是对字符进行存储管理,并且打印方式均一样,那么他们两个是否就是没区别呢?

vector和string都是C++中的容器,但它们有一些区别:

  • 数据类型: vector<char>是一个动态数组,可以存储char类型的元素,而string是一个字符串类,可以存储字符串。

  • 存储方式: vector<char>使用连续的内存块来存储元素,而string使用动态分配的内存来存储字符串。

  • 操作方式: vector<char>可以通过下标访问和修改元素,也可以使用迭代器进行遍历。而string提供了更多的字符串操作函数,比如查找、插入、删除等。

  • 字符串处理: string提供了更多的字符串处理功能,比如连接、截取、替换等操作,而vector<char>主要用于存储和处理字符序列。

  • 内存管理: vector<char>需要手动管理内存,包括分配和释放内存空间,而string会自动管理内存,不需要手动释放。

2.4 vector的迭代器

iterator的使用接口说明
begin + end(重点)获取第一个数据位置的iterator/const_iterator, 获取最后一个数据的下一个位置的iterator/const_iterator
rbegin + rend获取最后一个数据位置的reverse_iterator,获取第一个数据前一个位置的reverse_iterator

在这里插入图片描述

const对象使用const迭代器进行遍历打印

void PrintVector(const vector<int>& v)
{
	// const对象使用const迭代器进行遍历打印
	vector<int>::const_iterator it = v.begin();
	while (it != v.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;
}

使用迭代器进行遍历打印

	vector<int>::iterator it = v.begin();
	while (it != v.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;

使用迭代器进行修改

	vector<int>::iterator it = v.begin();
	while (it != v.end())
	{
		*it *= 2;
		++it;
	}

使用反向迭代器进行遍历再打印

	// vector<int>::reverse_iterator rit = v.rbegin();
	auto rit = v.rbegin();
	while (rit != v.rend())
	{
		cout << *rit << " ";
		++rit;
	}
	cout << endl;

	PrintVector(v);

2.5 vector 空间增长问题

先了解一下vector的容量空间

容量空间接口说明
size获取数据个数
capacity获取容量大小
empty判断是否为空
resize(重点)改变vector的size
reserve (重点)改变vector的capacity

这里主要对resize进行讲解,其他的均好理解

vector的resize

reisze(size_t n, const T& data = T())
将有效元素个数设置为n个,如果时增多时,增多的元素使用data进行填充
注意:resize在增多元素个数时可能会扩容

void TestVector3()
{
	vector<int> v;

	// set some initial content:
	for (int i = 1; i < 10; i++)
		v.push_back(i);

	v.resize(5);
	v.resize(8, 100);
	v.resize(12);

	cout << "v contains:";
	for (size_t i = 0; i < v.size(); i++)
		cout << ' ' << v[i];
	cout << '\n';
}

在这里插入图片描述

测试vector的默认扩容机制

原理: 在不手动改变vector的容量capacity的情况下,我们不断往vector中存入数据,vector在size将大于capacity的时候会进行扩容,我们存入的数据与容量相同的时候对容量进行打印输出,对值进行观察便可得到vector的默认扩容机制

void TestVectorExpand()
{
	size_t sz;
	vector<int> v;
	sz = v.capacity();
	cout << "making v grow:\n";
	for (int i = 0; i < 100; ++i)
	{
		v.push_back(i);
		if (sz != v.capacity())
		{
			sz = v.capacity();
			cout << "capacity changed: " << sz << '\n';
		}
	}
}

在这里插入图片描述

  • capacity的代码在vs和g++下分别运行会发现,vs下capacity是按1.5倍增长的,g++是按2倍增长的。 这个问题经常会考察,不要固化的认为,vector增容都是2倍,具体增长多少是根据具体的需求定义的。vs是PJ版本STL,g++是SGI版本STL。
  • reserve只负责开辟空间,如果确定知道需要用多少空间,reserve可以缓解vector增容的代价缺陷问题。
  • resize在开空间的同时还会进行初始化,影响size。

reserve提前扩容

如果已经确定vector中要存储元素大概个数,可以提前将空间设置足够
就可以避免边插入边扩容导致效率低下的问题了

void TestVectorExpandOP()
{
	vector<int> v;
	size_t sz = v.capacity();
	v.reserve(100); // 提前将容量设置好,可以避免一遍插入一遍扩容
	cout << "making bar grow:\n";
	for (int i = 0; i < 100; ++i)
	{
		v.push_back(i);
		if (sz != v.capacity())
		{
			sz = v.capacity();
			cout << "capacity changed: " << sz << '\n';
		}
	}
}

2.6 vector 增删查改

vector增删查改接口说明
push_back(重点)尾插
pop_back (重点)尾删
find查找。(注意这个是算法模块实现,不是vector的成员接口)
insert在position之前插入val
erase删除position位置的数据
swap交换两个vector的数据空间
operator[] (重点)像数组一样访问

尾插和尾删:push_back/pop_back

void TestVector4()
{
	vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);

	auto it = v.begin();
	while (it != v.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;

	v.pop_back();
	v.pop_back();

	it = v.begin();
	while (it != v.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;
}

在这里插入图片描述

insert和erase,以及查找find

注意find不是vector自身提供的方法,是STL提供的算法

void TestVector5()
{
	// 使用列表方式初始化,C++11新语法
	vector<int> v{ 1, 2, 3, 4 };

	// 在指定位置前插入值为val的元素,比如:3之前插入30,如果没有则不插入
	// 1. 先使用find查找3所在位置
	// 注意:vector没有提供find方法,如果要查找只能使用STL提供的全局find
	auto pos = find(v.begin(), v.end(), 3);
	if (pos != v.end())
	{
		// 2. 在pos位置之前插入30
		v.insert(pos, 30);
	}

	vector<int>::iterator it = v.begin();
	while (it != v.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;

	pos = find(v.begin(), v.end(), 3);
	// 删除pos位置的数据
	v.erase(pos);

	it = v.begin();
	while (it != v.end()) {
		cout << *it << " ";
		++it;
	}
	cout << endl;
}

在这里插入图片描述

operator[]+index

void TestVector6()
{
	vector<int> v{ 1, 2, 3, 4 };

	// 通过[]读写第0个位置。
	v[0] = 10;
	cout << v[0] << endl;

	// 1. 使用for+[]小标方式遍历
	for (size_t i = 0; i < v.size(); ++i)
		cout << v[i] << " ";
	cout << endl;

	vector<int> swapv;
	swapv.swap(v);

	cout << "v data:";
	for (size_t i = 0; i < v.size(); ++i)
		cout << v[i] << " ";
	cout << endl;

	// 2. 使用迭代器遍历
	cout << "swapv data:";
	auto it = swapv.begin();
	while (it != swapv.end())
	{
		cout << *it << " ";
		++it;
	}

	// 3. 使用范围for遍历
	for (auto x : v)
		cout << x << " ";
	cout << endl;
}


在这里插入图片描述

  • 98
    点赞
  • 75
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 110
    评论
好的,下面是用C++编程,用STL容器vector和partition实现快速排序功能的代码,并逐句解释: ```cpp #include <iostream> #include <vector> #include <algorithm> using namespace std; void quick_sort(vector<int>& nums, int left, int right); int partition(vector<int>& nums, int left, int right); int main() { vector<int> nums = {5, 1, 3, 8, 4, 2, 9, 6, 7}; quick_sort(nums, 0, nums.size() - 1); for (int num : nums) { cout << num << " "; } cout << endl; return 0; } void quick_sort(vector<int>& nums, int left, int right) { if (left < right) { int pivot = partition(nums, left, right); quick_sort(nums, left, pivot - 1); quick_sort(nums, pivot + 1, right); } } int partition(vector<int>& nums, int left, int right) { int pivot = nums[right]; int i = left; for (int j = left; j < right; ++j) { if (nums[j] < pivot) { swap(nums[i], nums[j]); ++i; } } swap(nums[i], nums[right]); return i; } ``` - `#include <iostream>` 用于输入输出流。 - `#include <vector>` 用于使用vector容器。 - `#include <algorithm>` 用于使用swap函数。 - `using namespace std;` 使用命名空间std。 - `void quick_sort(vector<int>& nums, int left, int right);` 声明快速排序函数。 - `int partition(vector<int>& nums, int left, int right);` 声明划分函数。 - `int main() { ... }` 主函数。 - `vector<int> nums = {5, 1, 3, 8, 4, 2, 9, 6, 7};` 定义一个名为nums的vector容器,并初始化为{5, 1, 3, 8, 4, 2, 9, 6, 7}。 - `quick_sort(nums, 0, nums.size() - 1);` 调用快速排序函数,对nums进行排序。 - `for (int num : nums) { ... }` 遍历nums中的元素,并输出。 - `void quick_sort(vector<int>& nums, int left, int right) { ... }` 快速排序函数的定义。 - `if (left < right) { ... }` 判断左右边界,若左边界小于右边界,则继续划分。 - `int pivot = partition(nums, left, right);` 调用划分函数,返回中间元素下标。 - `quick_sort(nums, left, pivot - 1);` 递归排序左边的子序列。 - `quick_sort(nums, pivot + 1, right);` 递归排序右边的子序列。 - `int partition(vector<int>& nums, int left, int right) { ... }` 划分函数的定义。 - `int pivot = nums[right];` 取最右边的元素作为中间元素。 - `int i = left;` 初始化i为左边界。 - `for (int j = left; j < right; ++j) { ... }` 遍历左右边界之间的元素。 - `if (nums[j] < pivot) { ... }` 如果当前元素小于中间元素,则交换当前元素和i所在位置的元素,并且i自增。 - `swap(nums[i], nums[right]);` 将中间元素放到正确位置。 - `return i;` 返回中间元素的下标。 以上就是用C++编程,用STL容器vector和partition实现快速排序功能的代码,并逐句解释。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 110
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

RO-BERRY

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值