STL容器
了解STL (Standard Template Library 标准模板库)
STL的三个主要组件
容器:各种数据结构,如vector、list、deque、set、map等,用来存放数据。
算法(algorithm):各种常用的算法,如sort、find、copy、for_each等
迭代器:用来遍历容器中的元素,且迭代器使用非常类似于指针
一、vector容器
可以理解为数组STL中最常用的容器为Vector,可以理解为数组。
和普通数组不同之处在于数组是静态空间,而vector可以动态拓展。
同时,vevtor并不是在原空间之后许接新空间,而是找更大的内存空间,然后将原数据拷贝到新空间,释放原空间。
默认构造&容器复制
vector<int> v1;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
两种复制方式
vector<int> v2;
v2.assign(v1.begin(), v1.end());
vector<int> v3(v1);
函数原型
-
插入和删除
-
- push_back() 向容器中放数据 - pop_back() 删除最后一个元素 - v1.insert(v1.begin(), 100); 在v1.begin()的位置插入100 - insert(v1.begin(), int count = 10,ele = 20);//迭代器指向位置pos插入10个元素20 - erase(pos); //删除pos迭代器所指的元素,返回下一个元素的迭代器。 - erase(beg, end); //删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。 - erase(elem); //删除容器中值为elem的元素。 - clear(); //删除容器中所有元素
容量和大小
-
- enpty() 判断容器是否为空 - capacity() 容器的容量 - size() 返回容器中元素的个数 - resize( int 40) 重新指定容器的长度为50,若容器变长,则以默认值填充新位置;如果容器变短,则末尾超出容器长度的元素被删除。 - resize( int 50, int 10) //重新指定容器的长度为50,若容器变长,则以10值填充新位置。
数据存取
-
- at(int idx); //返回索引idx所指的数据 - operator[]; //返回索引idx所指的数据 - front(); //返回容器中第一个数据元素 - back(); //返回容器中最后一个数据元素
-
互换容器
-
- v1.swap(v2) 实现两个容器内元素进行互换
预留空间
-
reserve( int len) 容器预留len个元素长度,预留位置不初始化,元素不可以访问
字符串指定个数输入
- 第一种方法
vector<int>v1(3);
for ( int &elem : v1) {
cin >> elem;
}
- 第二种方法
vector<int>v1;
int elem;
for ( int i = 0; i < 4; i++) {
cin >> elem;
v1.push_back(elem);
}
遍历写法
v.begin()返回迭代器,这个迭代器指向容器中第一个数据
v.end()返回迭代器,这个迭代器指向容器元素的最后一个元素的下一个位置
vector::iterator 拿到vector这种容器的迭代器类型
当用到for_each函数时,注意添加上#include 头文件
void MyPrint(int val)
{
cout << val << endl;
}
void test01() {
vector<int>::iterator pBegin = v.begin();
vector<int>::iterator pEnd = v.end();
//第一种遍历方式:
while (pBegin != pEnd) {
cout << *pBegin << endl;
pBegin++;
}
//第二种遍历方式:
for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
cout << *it << endl;
}
cout << endl;
//第三种遍历方式:
//使用STL提供标准遍历算法 头文件 algorithm
for_each(pBegin, pEnd, MyPrint);
for_each(v.begin(), v.end(), MyPrint);
}
deque容器
- 双端数组,可以对头端进行插入和删除操作
默认构造&容器复制
deque<int> d1;
for (int i = 0; i < 10; i++)
{
d1.push_back(i);
}
两种复制方式
deque<int> d2;
d2.assign(d1.begin(), d1.end());
deque<int> d3(d2);
函数原型
在原有的vector容器中增加了以下函数:
注意: deque容器没有capacity的概念,并且在pop_back或者pop_front中括号中是不用给定参数的。 因为vector容器并没有指定是否是最后一个元素,所以需要在erase中指定删除的下标。
- push_front(10) 在头部插入数据10
- pop_front() 删除容器第一个数据
排序算法
sort算法非常实用,使用时包含头文件 algorithm即可
sort(d.begin(), d.end());
二、string容器
string本质上是一个类,类内部封装了char*管理这个字符串。
- 字符串赋值
//头文件
#include <string>
// 三种方式
str1 = "hello world";
string str2 = str1;
str4.assign("hello c++");
}
- 字符串的拼接的两种方式
string str1 = "我";
str1 += "爱玩游戏";
string str3 = "I";
str3.append(" love ");
- string的查找和替换
str2.find("ao") != -1
str2.rfind("ao") != -1 从右向左查,并返回元素的起始位置
str2.replace(0, 5, str1);
cout << str2 << endl;
}
一个例子:
查找字符串中存在多少待查的子串
string mainString = "abababcababcabab";
string subString = "ab";
int pos = mainString.find(subString); // 查找子串的第一次出现位置
int count = 0;
while (pos != string::npos) {
// 找到一个子串后,继续在剩余部分查找
count++;
//find( 待查找的字符串, 找到的字符的下一个位置)
pos = mainString.find(subString, pos + subString.length());
}
如果 subString 存在于 mainString 中,find 函数返回子串在字符串中的位置,否则返回 string::npos,用于表示未找到。
- 字符串比较
string s1 = "hello";
string s2 = "aello";
int ret = s1.compare(s2);
- 字符串修改
str[0] = 'x';
str.at(1) = 'x';
- 字符串的插入和删除
erase函数的两个参数 第一个是开始的位置,第二个是从该位置开始 的几个元素
//字符串插入和删除
void test01()
{
string str = "hello";
str.insert(1, "111");
cout << str << endl;
str.erase(1, 3); //从1号位置开始3个字符
cout << str << endl;
}
int main() {
test01();
system("pause");
return 0;
}
- string子串
string substr(int pos = 0, int n = npos) const; //返回由pos开始的n个字符组成的字符串
string str = "abcdefg";
string subStr = str.substr(1, 3);
cout << "subStr = " << subStr << endl;
string email = "hello@sina.com";
int pos = email.find("@");
string username = email.substr(0, pos);
cout << "username: " << username << endl;
三、stack容器
stack是一种先进后出的数据结构,又叫栈。
#include <stack>
stack<int> s;
- 数据存取:
push(elem); //向栈顶添加元素
pop(); //从栈顶移除第一个元素
top(); //返回栈顶元素 - 大小操作:
empty(); //判断堆栈是否为空
size(); //返回栈的大小
栈不支持直接在定义的时候指定大小,所以可以采用for循环的形式将元素压入栈,并且通过判断栈是否为空遍历栈中的元素(逆序输出)
stack<int> v1;
int elem;
for ( int i = 0; i < 4; i++) {
cin >> elem;
v1.push(elem);
}
while ( !v1.empty()) {
cout << v1.top() << " ";
v1.pop();
}
cout << endl;
四、queue容器
queue是一种先进先出的数据结构,又叫队列。
-
数据存取:
push(elem); //往队尾添加元素
pop(); //从队头移除第一个元素
back(); //返回最后一个元素
front(); //返回第一个元素 -
大小操作:
empty(); //判断堆栈是否为空
size(); //返回队的大小
queue<int> v1;
int elem;
for ( int i = 0; i < 4; i++) {
cin >> elem;
v1.push(elem);
cout << v1.back() << " ";
}
cout << endl << "大小:" << v1.size() << endl;
while ( !v1.empty()) {
cout << v1.front() << " ";
v1.pop();
}
cout << endl;
五、list容器
和deque一定的不同
- 在指定位置插入元素
**auto it = v1.begin();
advance(it, 2);
v1.insert(it, 35);**
- 排序
因为list不支持随机访问迭代器,而sort函数通常期望能够直接访问容器中的元素。所以我们采用list自带的sort函数。
v1.sort();
- 移除元素
移除的为删除容器中所有与11匹配的元素。
v1.remove(11);
- 翻转链表
v1.reverse();
六、set/multiset容器
所有元素都会在插入时自动被排序其底层使用的是二叉树实现
-
set和multiset区别:
-
set不允许容器中有重复的元素 multiset允许容器中有重复的元素 **set插入数据的同时会返回插入结果,表示插入是否成功**
注意: 使用multiset之间在创建的时候写成下面的形式,不是修改头文件,头文件依旧是#include
multiset<int>v1;
set构造和赋值
set容器插入数据时用insert
v1.insert(elem);
基本函数
- insert
- erase
- clear
- find
- count
- size
- empty
- swap
set查找与统计
-
find(key); //查找key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回set.end();
-
count(key); //统计key的元素个数 但是对于set而言除了0就是1
-
set不支持指定位置删除元素,但是可以采用下面的方法
auto it = v1.begin();
advance(it, 2);
v1.erase(it);
- find函数的应用
set<int>::iterator pos = v1.find(13);
if (pos != v1.end()) {
cout << "找到了元素" << endl;
} else {
cout << "未找到元素" << endl;
}
pair对组创建
成对出现的数据,利用对组可以返回两个数据
两种创建方式:
pair<type, type> p ( value1, value2 );
pair<type, type> p = make_pair( value1, value2 );
利用仿函数改变排列规则
使用仿函数要在创建的时候就指定排列规则
class MyCompare
{
public:
bool operator()(int v1, int v2) {
return v1 > v2;
}
};
七、map/ multimap容器
-
特点:
-
- map中所有元素都是pair - pair中第一个元素为key(键值),起到索引作用,第二个元素为value(实值) - 所有元素都会根据元素的键值自动排序 - 其底层也是使用二叉树实现的。 - 可以根据key值快速找到value值 - 很多功能同set容器
- map的创建
map<int,int>m; //默认构造
- map的插入方式
m.insert(make_pair(2, 20));
- 利用防函数排序
class MyCompare {
public:
bool operator()(int v1, int v2) {
return v1 > v2;
}
};
map<int, int, MyCompare> m;
- map的遍历输出
for (map<int, int, MyCompare>::iterator it = m.begin(); it != m.end(); it++) {
cout << "key:" << it->first << " value:" << it->second << endl;
}