C++的STL(一)

一、基本概念

STL分为三部分:算法、容器、迭代器。C++中的STL主要有以下头文件:

#include <algorithm>
#include <deque>
#include <functional>
#include <iterator>
#include <vector>
#include <list>
#include <map>
#include <memory>
#include <queue>
#include <set>
#include <stack>

二、容器

1.分类

容器分为两类:序列式容器和关联式容器。

序列式容器:每个元素都有固定的位置,取决于插入元素的时机和地点,与元素值无关。

例如:vector、deque、list、queue、stack。

关联式容器:元素位置取决于特定的排序规则,与插入元素顺序无关。

例如:set、mulitset、map、mutilmap

2.介绍

  1. 向量(vector):连续存储的元素。头文件<vector>。
  2. 列表(list):由节点组成的双向链表,每个节点包含一个元素。头文件<list>。
  3. 双队列(deque):连续存储的指向不同元素的指针所组成的数组。头文件<deque>。
  4. 集合(set):由节点组成的红黑树,每个节点包含一个元素,节点之间由某种作用于元素的谓词排列,没有两个不同的元素能够拥有相同的次序(set中不存在相同的元素,可以去重)。头文件<set>。

3.vector

一个动态数组,在尾部加入或删除元素较快,在中部和头部相对较慢。

3.1 vector的构造

int main() {

	// vector
	
	// 1. vector的默认构造
	vector<int> vec;

	// 2. vector的带参构造
	int array[] = { 1,2,3,4,5 };
	vector<int> v1(array, array + 5);	// 左闭右开,把数组array复制给v1
	vector<int> v2(4, 10);	// 存储3个10
	vector<int> v3(v2);	// 拷贝构造,参数是另一个vector的引用,就是用一个构造好的vector去初始化另一个vector
	vector<int> v4 = v2;
	
}

3.2 vector元素赋值

这里用到了assign()、swap()函数和运算符重载三种方式。

int main() {

    // vector元素赋值

	// 1. assign:会清空原vector
	vector<int> vecA, vecB, vecC, vecD, vecE;
	int array[] = { 1,2,3,4,5,6 };
	vecA.assign(array, array + 6);	// 左闭右开
	vecB.assign(5, 10);				// 存放5个10
	vecC.assign(vecA.begin(), vecA.end());		// vecA.begin()是vecA中的第一个元素地址,vecA.end()是vecA中的最后一个元素地址

	// 2. swap()函数:互换两个vector的值
	vecD.swap(vecC);

	// 3. 利用重载运算符
	vecE = vecA;

}

3.3 vector的大小

这里主要介绍几个函数:

  1. vector.size():返回vector的长度
  2. vector.empty():判断是否为空
  3. vector.resize():重新定义vector的长度,若边长,就用默认值填充;若变短,就删除末尾元素。
  4. vector.resize(int num, class elem):重新定义vector的长度,若边长,用elem填充。
int main() {

	// vector元素的大小

	// 1. size()  empty()
	vector<int> vecA, vecB, vecC;
	int array[] = { 1,2,3,4,5,6 };
	vecA.assign(array, array+6);
	cout << "vecA size:" << vecA.size() << endl;
	cout << "vecA is empty? " << vecA.empty() << endl;

	// 2. resize(int)  resize(int , class)
	vecB = vecA;
	vecB.resize(10);
	vecC = vecA;
	vecC.resize(10, 99);
	for (int i = 0; i < vecB.size(); i++) {
		cout << vecB.at(i) << "  ";
	}
	cout << endl;
	for (int i = 0; i < vecC.size(); i++) {
		cout << vecC.at(i) << "  ";
	}

}

3.4 vector访问元素

用下标的方式访问:vec[index],如果下标越界,程序会异常终止。

使用at(index)函数,越界的话会抛出一个异常。

	// vector访问元素

	// at(index) 函数
	int array[] = { 1,2,3,4,5 };
	vector<int> vec(array, array + 5);
	cout << vec.at(4);

3.5 vector插入元素

我们可以在vector的任意位置添加或删除元素

  1. 在末尾添加元素push_buck(elem)
  2. 在末尾删除元素pop_back()
  3. 在中间位置添加元素:vector.insert()
	// vector插入元素
	int array[] = { 1,2,3,4,5,6 };
	vector<int> vecA(array, array + 6), vecB(array, array + 6), vecC(array, array + 6), vecD(array, array + 6), vecE(array, array + 6);

	// 1. 在末尾添加元素push_back(elem)
	vecA.push_back(7);
	for (int i = 0; i < vecA.size(); i++) {
		cout << vecA.at(i) << "  ";
	}
	cout << endl;

	// 2. 在末尾删除元素
	vecB.pop_back();
	for (int i = 0; i < vecB.size(); i++) {
		cout << vecB.at(i) << "  ";
	}
	cout << endl;

	/*3. 在中间添加元素insert()
		3.1 insert(pos, elem):在pos位置处插入元素elem,并返回位置
		3.2 insert(pos, n, elem):在pos位置处插入n和元素elem,无返回值
		3.3 insert(pos, begin, end):在pos处插入[begin, end)的元素,无返回值
		vec: {1,2,3,4,5,6}
	*/ 
	vecC.insert(vecC.begin()+2, 100);
	vecD.insert(vecD.begin() + 2, 10, 100);
	vecE.insert(vecE.begin() + 2, array + 3, array + 5);

	
	for (int i = 0; i < vecC.size(); i++) {
		cout << vecC.at(i) << "  ";
	}
	cout << endl;
	for (int i = 0; i < vecD.size(); i++) {
		cout << vecD.at(i) << "  ";
	}
	cout << endl;
	for (int i = 0; i < vecE.size(); i++) {
		cout << vecE.at(i) << "  ";
	}
	cout << endl;

4.迭代器

4.1 概念

迭代器是一种检查容器内元素并遍历元素的数据类型。迭代器的作用是提供对一个容器中对象的访问方法,并且定义了容器中对象的范围。

使用迭代器去访问元素,不用[index]方法,也不要.at()函数。

4.2 为什么要用到迭代器?

  1. STL中各种容器的实现原理不同,访问元素方式也不同,很麻烦。而每个容器都实现了一个迭代器用于对元素的访问。
  2. 像使用指针遍历的话,只能一个一个移动。而迭代器可以一次移动多个位置,效率要好一些。

4.3 使用

    int array[] = { 1,2,3,4,5,6 };
	vector<int> vecIntA(array, array + 6), vecIntB;

	// 构造一个迭代器对象
	vector<int>::iterator iter;
	/*
		1. 用迭代器it指向容器中的第一个元素;begin()函数,这个iter本质上就是一个指针
	*/
	iter = vecIntA.begin();
	cout << *iter << endl;

	/*
		2. 通过循环的方式 使用迭代器遍历元素
	*/
	for (vector<int>::iterator it = vecIntA.begin(); it < vecIntA.end(); it++) {
		cout << *it << "  ";
	}
	cout << '\n';

	/*
		iter的加减
	*/
	iter = vecIntA.begin();
	cout << *(iter + 2) << "   " << *(iter + 1) << endl;

4.4 迭代器的失效

    // 迭代器的失效
	int array[] = { 1,2,3,4,5 };
	vector<int> vecIntA(array, array + 5);
	vector<int>::iterator iter = vecIntA.begin() + 4;
	cout << *iter << endl;
4.4.1 insert

在以上代码基础上,在vector中新增或删除一个元素,这时迭代器会失效。

vecIntA.insert(iter-1, 100);

因为会把原有内存被释放掉,再去开辟一个新的内存存放元素,原iter成为一个野指针。但是不要慌,insert函数会返回一个新的迭代器newIt,newIt指向了新的vector内存空间中保存新增元素的那个地址。

    int array[] = { 1,2,3,4,5 };
	vector<int> vecIntA(array, array + 5);
	vector<int>::iterator iter = vecIntA.begin() + 4;
	cout << *iter << endl;
	
	// insert会返回一个新的有效的迭代器
	vector<int>::iterator newIt = vecIntA.insert(iter-1, 100);
	
	cout << *newIt << endl;
4.4.2 erase

删除vector中的元素也会导致迭代器失效,有如下vector:

    // 迭代器的失效:erase
	vector<int> vecIntA = { 1,2,3,3,3,3,3,4,5 };
	vector<int>::iterator iter = vecIntA.begin();

现在要将容器中的3全部删除,则以下代码不行:

	for (vector<int>::iterator it = vecIntA.begin(); it < vecIntA.end();) {
		if (*it == 3) {
			vecIntA.erase(it);
		}
		else
		{
			it++;
		}
	}

这是因为迭代器在执行一次erase后会失效,但erase函数会返回一个新迭代器,与insert相同。

以下代码正确:

    for (vector<int>::iterator it = vecIntA.begin(); it < vecIntA.end();) {
		if (*it == 3) {
			it = vecIntA.erase(it);
		}
		else
		{
			it++;
		}
	}

  • 20
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值