C++ STL基础学习

标准模板库

  • STL(Standard Template Library),是一些常用数据结构和算法的模板的集合,主要由 Alex Stepanov 主持开发,于 1998 年被加入 C++ 标准。

容器

  • 容器(container)用于存放数据的类模板。
  • 可变长数组、链表、平衡二叉树等 数据结构 在 STL 中都被实现为容器。

容器分类

  • 顺序容器:vector 、deque(双端队列) 、 list(双向列表)

    之所以被称为顺序容器,是因为元素在容器中的位置同元素的值无关,即容器不是排序的。

    将元素插入容器时,指定在什么位置(尾部、头部或中间某处)插入,元素就会位于什么位置。

  • 关联容器:set 、 multiset 、 map 、 multimap

    关联容器内的元素是排序的。插入元素时,容器会按一定的排序规则将元素放到适当的位置上,因此插入元素时不能指定位置。

容器适配器

  • STL 还在两类容器的基础上屏蔽一部分功能,突出或增加另一部分功能,实现了三种容器适配器:栈 stack、队列 queue、优先级队列 priority_queue。

成员函数

  • 所有容器都有的两个成员函数

    1. int size() 返回容器对象中元素的个数
    2. bool empty() 判断容器是否为空
  • 顺序容器和关联容器共有的成员函数

    1. begin() 返回指向容器中第一个元素的迭代器
    2. end() 返回指向容器中最后一个元素后面的位置的迭代器
    3. rbegin() 返回指向容器中最后一个元素的反向迭代器。
    4. rend() 返回指向容器中第一个元素前面的位置的反向迭代器。
    5. erase(...) 从容器中删除一个或几个元素。
    6. clear() 从容器中删除所有元素。

    Ps:一个容器是空的,则 begin() 和 end() 的返回值相等,rbegin() 和 rend() 的返回值也相等。

  • 顺序容器成员函数

    1. front():返回容器中第一个元素的引用。
    2. back():返回容器中最后一个元素的引用。
    3. push_back():在容器末尾增加新元素。
    4. pop_back():删除容器末尾的元素。
    5. insert(...):插入一个或多个元素。
  • 关联容器成员函数

    1. find:查找某个值。
    2. lower_bound:查找某个下界。
    3. upper_bound:查找某个上界。
    4. equal_range:同时查找上界和下界。
    5. count:计算等于某个值的元素个数。
    6. insert:插人一个元素或一个区间。

迭代器的定义

正向迭代器 <容器类名>::iterator 迭代器名

反向迭代器 <容器类名>::reverse_iterator 迭代器名;

常量正向迭代器 <容器类名>::const_iterator 迭代器名

常量反向迭代器 <容器类名>::const_reverse_iterator 迭代器名;

容器适配器 stack、queue 和 priority_queue 没有迭代器。

迭代器 支持随机访问迭代器 支持双向迭代器 不支持迭代器
容器 vector、deque list、set/multiset、map/multimap stack、queue/priority queue

迭代器都可以进行 ++操作

#include <iostream>
#include <vector>
using namespace std;
int main()
{
	vector<int> v; // 创建vector容器
	for (int n = 0; n < 5; ++n)
		// push_back成员函数在vector容器尾部添加一个元素
		v.push_back(n);
	// 定义正向迭代器 i
	vector<int>::iterator i;
	// 用迭代器遍历容器
	for (i = v.begin(); i != v.end(); ++i)
		cout << *i << " ";

	cout << endl;
	// 定义反向迭代器 j
	for (vector<int>::reverse_iterator j = v.rbegin(); j != v.rend(); ++j)
		cout << *j << " ";
	return 0;
}

程序输出的结果:

0 1 2 3 4

4 3 2 1 0

常用辅助函数

  • advance(p, n):使迭代器 p 向前或向后移动 n 个元素。
  • distance(p, q):计算两个迭代器之间的距离,即迭代器 p 经过多少次 + + 操作后和迭代器 q 相等。如果调用时 p 已经指向 q 的后面,则这个函数会陷入死循环。
  • iter_swap(p, q):用于交换两个迭代器 p、q 指向的值。

上述模板的使用需要包含< algorithm>头文件。

#include <list>
#include <iostream>
// 要使用操作迭代器的函数模板,需要包含此文件
#include <algorithm>
using namespace std;
int main()
{
	int a[5] = {1, 3, 5, 7, 9};
	// 将数组装进list容器
	list<int> lst(a, a + 5);
	// 是迭代器指向第一个元素
	list<int>::iterator p = lst.begin();
	// p向后移动两个元素,指向第三个元素
	advance(p, 2);
	cout << *p << endl; // 输出第三个元素5
	// p向前移动一个元素,指向第二个元素
	advance(p, -1);
	cout << *p << endl; // 输出第二个元素3
	// 是迭代器指向容器内最后一个元素后面的位置
	list<int>::iterator q = lst.end();
	// 是迭代器指向的位置前移一位
	q--;
	// 输出p元素与q元素的距离,即第三个元素和第五个元素的距离是3
	cout << distance(p, q) << endl;

	// 交换 p元素 和 q元素 的位置
	iter_swap(p, q);
	// 遍历输出容器内所有元素
	for (p = lst.begin(); p != lst.end(); ++p)
		cout << *p << " ";
	return 0;
}

程序输出的结果

5 3 3 1 9 5 7 3

  • find:在容器中查找元素

    该函数在头文件和头文件里都有,用法大致相同但不一样

    find(first,last) 注意:这是一个左闭右开的区间,即 last 不在查找范围内

#include <vector>
#include <algorithm> //包含头文件
#include <iostream>
using namespace std;
int main()
{
	int a[10] = {10, 20, 30, 40};
	vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	// 此时v里放着4个元素:1,2,3,4
	// 定义一个迭代器p
	vector<int>::iterator p;
	// 在v中查找元素 3
	p = find(v.begin(), v.end(), 3);
	// 若找不到,find返回 v.end()
	if (p != v.end())
		// 找到元素 3 就输出
		cout << *p << endl;
	p = find(v.begin(), v.end(), 9);
	if (p == v.end())
		// 如果没找到,打印NULL
		cout << "NULL" << endl;
	p = find(v.begin() + 1, v.end() - 1, 4);
	// 在2,3这两个元素中查找4
	cout << *p << endl;
	// 为什么会输出4呢?因为返回的是end()
	// 在数组a中所有元素中查找20
	int *pp = find(a, a + 4, 20);
	if (pp == a + 4)
		cout << "NULL" << endl;
	else
		cout << *pp << endl;
	return 0;
}

程序运行结果:

3 NULL 4 20

STL—vector

vector 容器在实现时,动态分配的存储空间一般都大于存放元素所需的空间。哪怕容器中只有一个元素,也会分配 32 个元素的存储空间。

这样做的好处是,在尾部添加一个新元素时不必重新分配空间,直接将新元素写入适当位置即可。在这种情况下,添加新元素的时间是常数。

当元素个数超过32个时,就会重新分配空间,并将原有内容copy到新空间。

vector容器的初始化:

vector v; 空容器

vector v(10); 初始化10个0

vector v(3,6); 初始化3个6

vector v{1,3,5,7,9}; 初始化1,3,5,7,9

vector<vector > v; 嵌套形成二维数组

方法:

v.push_back(x); 追加一个元素x

v.erase(v.begin()); //删除第一个元素

v.erase(--v.end()); //删除最后一个元素

v.resize(10);//重置容器大小为10,不赋值默认为0

cout<<v.front(); //获取第一个元素

cout<<v[0];

cout<<*v.begin();

cout<<v.back(); //获取最后一个元素

cout<<v[v.size()-1];

cout<<*--v.end();

sort(v.begin(),v.end(),less()); //从小到大排序,第三个参数默认可省略

sort(v.begin(),v.end(),greater()); //从大到小排序,第三个参数不可省略

for(int i=0;i<v.size();i++) cout<<v[i];//for循环

for(vector::iterator it=v.begin();it!=v.end();it++) cout<<*it;;//迭代器循环

for(auto it=v.begin();it!=v.end();it++) cout<<*it;//迭代器简化循环

for(auto x:v) cout<<x; (C++11新特性)

STL—deque

比之vector,它可以

dq.pop_front(); //删除头元素

dq.push_front(x); //增加头元素

STL—list

list lst; //初始化

方法

lst.push_back(x); //尾部插入元素x

lst.push_front(x); //头部插入元素x

lst.emplace_front(x); //头部插入一个元素

lst.emplace_back(x); //尾部插入元素x

lst.insert(++li.begin(), x);//在第二个元素位置插入一个元素

lst.pop_front(); //删除第一个元素

lst.pop_back(); //删除最后一个元素

lst.clear(); //清空容器

算法 sort 需要随机访问迭代器的支持,list 不支持随机访问迭代器。

因此,list 容器引入了 sort 成员函数以完成排序。

lst.sort(); //从小到大排序

lst.sort(greater()); //从大到小排列

STL—set/multiset

set multiset
不允许有相同的元素 允许有相同的元素

set s;

multiset::iterator s;

s.insert(x); //增加一个元素x

s.erase(x); //删除元素x

cout<<*s.lower_bound(x); //打印第一个大于或者等于x的元素

cout<<*s.upper_bound(x); //打印第一个大于x的元素

cout<<*s.find(x); //打印一个被查找到的元素

STL—map/multimap

有序,键值对(key-value),key具有唯一性

map<int,string> m;

m[1]="first";//增加元素

m[2]="second";

m.insert(pair<int,string>(3,"third"));//插入元素

m.insert(map<int,string>::value_type(4,"fourth"));

利用迭代器删除元素

map<int,string>::iterator it;

it = m.find(1);

m.erase(it);

清空map

m.erase(m.begin(),m.end());

STL—stack/queue/priority_queue

容器适配器是在顺序容器的基础上实现的,没有迭代器。

因此 STL 中的各种排序、查找、变序等算法都不适用于容器适配器。

  • push 入栈一个元素
  • pop 出栈一个元素,pop无返回值
  • top 取栈顶元素
  • size 查看元素个数

STL——string

string str("hello"); //str="hello "

string str(5,"A"); //str="AAAAA"

string str("12345",1,2); //str="23"

string str("hello");

str+="world"; //连接两段字符串

cout<<str;

string str;

s+=65; //ASCLL码转换

cout<<str;

string str;

getline(cin,str);//输入一行数据进入s

cout<<str;

string str("546123987")

sort(s.begin(),s.end()); //排序

str.erase(s.begin()); //删除第一个元素

str.erase(--s.end());

string str="456321789";

str=str.substr(1,3); //str="563" 截取子串

posted @ 2020-05-04 21:34  予之路  阅读(98)  评论(0编辑  收藏  举报