2.1 string
\1. string和char*有什么区别呢?
string是类,而char*是一个指向字符串的指针;string是一个char *类型的容器,它封装了char *,以及字符串操作相关的函数,并且string可以自动管理内存,不用考虑内存回收和访问越界问题。
\2. string类中at成员函数和[]操作符区别?
当访问越界时,at可以抛出异常,[]直接编译报错。
\3. 常用成员函数整理
//构造函数
string();
string(const string &str);
string(const char *s);
string(int n,char c);
//字符访问
const char &operator[] (int n) const;
const char &at(int n) const;
char &operator[] (int n);
char &at(int n);
//获取字符串const char *
const char *c_str() const;
//字符拷贝
int copy(char *s, int n, int pos=0) const;
//字符串长度
int length() const;
//判断字符串是否为空
bool empty() const;
//字符串赋值
string &operator=(const string &s);
string &assign(const char *s); //该函数有多个重载
//字符串追加(连接)
string &operator+=(const string &s);
string &operator+=(const char *s);
string &append(const char *s); //该函数有多个重载
//字符串比较
int compare(const string &s) const;
int compare(const char *s) const;
//查找
int find(char c,int pos=0) const; //该函数有多个重载
//替换
string &replace(int pos, int n, const char *s); //该函数有多个重载
//插入
string &insert(int pos, const char *s);
//删除
string &erase(int pos=0, int n=npos);
2.2 vector
\1. vector为什么在尾部插入删除效率更高?
vector是一个动态单端数组,在尾部插入和删除效率更高,原因是在头部或者中间插入元素,那么插入位置后面的元素都要往后移一位,在头部或者中间删除一个元素,那么被删除元素后面的元素都会往前移动一位,这会产生大量的元素移动,所以效率和速度较低。在尾部插入或删除就不会产生这样的大量元素移动。
\2. []和push_back的区别
[]操作时必须提前分配内存,而push_back不需提前分配内存,push_back是动态分配内存的;
[]可以随机存取,push_back只能在尾部插入元素;
vector<int> v(10);
v.push_back(1);
v.push_back(2);
//v.size() = 12 因为push_back是在尾部插入,会动态分配内存
\3. 迭代器的指向
begin()指向第一个元素,而end()指向最后一个元素的后面位置。
| 容器元素 | 1 | 2 | 3 | |
|---|---|---|---|---|
| 迭代器 | 🔺 begin() | |||
| 🔺 end() |
erase在删除元素后会自动使迭代器 it 后移,并返回移动后的迭代器位置.
//删除容器中的元素2
for(vector<int>::iterator it = v.begin(); it != v.end();)
{
if(*it == 2)
{
it = v.erase(it); //erase在删除元素后会自动使迭代器 it 后移,并返回移动后的迭代器位置
}
else
{
it++;
}
}
\3. 常用成员函数
vector.size(); //容器大小
vector.empty(); //容器是否为空
vector.resize(len); //重新指定大小
vector.assign(beg,end); //将[beg, end)的值拷贝复制
vector.push_back(e); //在尾部放入元素
vector.at(index); //访问index处的元素 可抛出异常
vector[index]; //访问index处的元素
vector.front(); //返回头部元素
vector.back(); //返回尾部元素
vector.insert(pos,e); //在pos处插入e //该函数有多个重载
vector.clear(); //移除容器的所有数据
vec.erase(beg,end); //删除[beg, end)区间内数据 //该函数有多个重载
2.3 deque
双端数组,两端都可以插入删除。
deque.push_back(e); //在容器尾部放入一个数据
deque.push_front(e); //在容器头部放入一个数据
deque.pop_back(); //删除容器最后一个数据
deque.pop_front(); //删除容器第一个数据
deque.at(index); //访问index处数据,可抛出异常
deque[index]; //访问index处数据,不可抛出异常
deque.begin(); //返回容器中第一个元素的迭代器
deque.end(); //返回容器中最后一个元素的迭代器
deque.size();
deque.empty();
deque.resize(len);
deque.insert(pos, e); //含有多个重载
deque.clear();
deque.erase(beg,end);
deque.erase(pos);
2.4 stack
栈,后进先出。
stack.push(e); //入栈
stack.pop(); //出栈
stack.top(); //返回栈顶元素
stack.size(); //栈大小
stack.empty(); //栈判空
2.5 queue
queue队列,先进先出,固定一端进一端出,队尾进,队头出。priority_queue 是优先级队列。
queue.push(e); //往队尾添加元素
queue.pop(); //弹出队头的元素
queue.back();
queue.front();
queue.empty();
queue.size();
2.6 list
双向链表,不支持随机访问,所以迭代器 it 不能 it+2 这种操作,一次只能移动一步 it++。
list.push_back(e); //尾插
list.push_front(e); //头插
list.pop_back(); //删除链表中尾部元素
list.pop_front(); //删除链表中头部元素
list.front(); //返回链表一个元素
list.back(); //返回链表最后一个元素
list.begin(); //返回链表第一个元素的迭代器
list.end(); //返回链表尾部元素的迭代器
list.size();
list.empty();
list.resize(num);
list.insert(pos,e); //含有多个重载
list.clear(); //移除链表的所有数据
list.erase(beg,end); //删除[beg, end)区间内数据 //多个重载
list.reverse(); //反转链表
2.7 set
集合容器,元素唯一且按一定规则有序排列,multi_set 同一值可以出现多次。
2.8 map
键值对容器<key, value>,键值key唯一,且按照一定规则排序,可以根据key随机访问对应value,也就是说对key支持[]操作。multi_map,相同键值可以重复。
\1. insert插入和[]插入有什么区别?
map<int, string> m;
m.insert(make_pair(1, "string1"));
m.insert(make_pair(1, "string2")); //插入失败
m[3] = "string3";
m[3] = "string4"; //覆盖原来的
\2. 常用成员函数
//元素插入
map.insert(pair<int, string>(1, "111"));
map.insert(make_pair(1, "111"));
map.insert(map<int, string>::value_type(1, "111"));
map[1] = "111";
map.size();
map.empty();
map.clear();
map.erase(pos);
map.find(key);
2.9 区别与相同点
\1. 区别
| vector | stack | queue | deque | list | set | multi_set | map | multi_map | |
|---|---|---|---|---|---|---|---|---|---|
| 数据结构 | 单端数组 | 栈 | 队列 | 双端数组 | 双向链表 | 二叉树 | 二叉树 | 二叉树 | 二叉树 |
| 随机访问 | 支持 | 不支持 | 不支持 | 支持 | 不支持 | 不支持 | 不支持 | 对key支持 | 不支持 |
\2. 相同点
所有容器提供的都是值语意(value),而不是引用语意(reference)。也就是说向容器中插入元素时,实行的是拷贝行为。所以,向容器中装入元素时必须保证元素能够被拷贝(必须提供拷贝构造函数实现深拷贝)。
3. STL算法
STL中常用算法的算法原型整理如下
//查找重复元素
_NODISCARD _FwdIt adjacent_find(const _FwdIt _First, _FwdIt _Last, _Pr _Pred);
_NODISCARD _FwdIt adjacent_find(const _FwdIt _First, const _FwdIt _Last);
//二分查找(有序数列)
_NODISCARD bool binary_search(_FwdIt _First, _FwdIt _Last, const _Ty& _Val, _Pr _Pred);
_NODISCARD bool binary_search(_FwdIt _First, _FwdIt _Last, const _Ty& _Val);
//计数
_NODISCARD _Iter_diff_t<_InIt> count(const _InIt _First, const _InIt _Last, const _Ty& _Val);
//计数(符合条件元素个数)
_NODISCARD _Iter_diff_t<_InIt> count_if(_InIt _First, _InIt _Last, _Pr _Pred);
//查找等于_Val的元素
_NODISCARD _InIt find(_InIt _First, const _InIt _Last, const _Ty& _Val);
//根据条件查找
_NODISCARD _InIt find_if(_InIt _First, const _InIt _Last, _Pr _Pred);
//合并两个有序序列
_DestTy* merge(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _DestTy (&_Dest)[_DestSize], _Pr _Pred);
_OutIt merge(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _OutIt _Dest, _Pr _Pred);
_DestTy* merge(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _DestTy (&_Dest)[_DestSize]);
_OutIt merge(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _OutIt _Dest);
//排序
void sort(const _RanIt _First, const _RanIt _Last, _Pr _Pred);
void sort(const _RanIt _First, const _RanIt _Last);
//随机排序
void random_shuffle(_RanIt _First, _RanIt _Last, _RngFn&& _RngFunc);
void random_shuffle(_RanIt _First, _RanIt _Last);
//倒序
void reverse(const _BidIt _First, const _BidIt _Last);
//复制
_DestTy* copy(_InIt _First, _InIt _Last, _DestTy (&_Dest)[_DestSize]);
_OutIt copy(_InIt _First, _InIt _Last, _OutIt _Dest);
//替换
void replace(const _FwdIt _First, const _FwdIt _Last, const _Ty& _Oldval, const _Ty& _Newval);
//按条件替换
void replace_if(const _FwdIt _First, const _FwdIt _Last, _Pr _Pred, const _Ty& _Val);
//交换
void swap(tuple<_Types...>& _Left, tuple<_Types...>& _Right);
void swap(basic_string<_Elem, _Traits, _Alloc>& _Left, basic_string<_Elem, _Traits, _Alloc>& _Right);
void swap(function<_Fty>& _Left, function<_Fty>& _Right);
void swap(_Ty (&_Left)[_Size], _Ty (&_Right)[_Size]);
void swap(_Ty& _Left, _Ty& _Right);
void swap(weak_ptr<_Ty>& _Left, weak_ptr<_Ty>& _Right);
void swap(shared_ptr<_Ty>& _Left, shared_ptr<_Ty>& _Right);
void swap(pair<_Ty1, _Ty2>& _Left, pair<_Ty1, _Ty2>& _Right);
//填充
void fill(const _FwdIt _First, const _FwdIt _Last, const _Ty& _Val);
//集合并集
_DestTy* set_union(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _DestTy (&_Dest)[_DestSize], _Pr _Pred);
_DestTy* set_union(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _DestTy (&_Dest)[_DestSize]);
_OutIt set_union(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _OutIt _Dest, _Pr _Pred);
_OutIt set_union(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _OutIt _Dest);
//交集
_DestTy* set_intersection(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _DestTy (&_Dest)[_DestSize], _Pr _Pred);
_DestTy* set_intersection(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _DestTy (&_Dest)[_DestSize]);
_OutIt set_intersection(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _OutIt _Dest, _Pr _Pred);
_OutIt set_intersection(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _OutIt _Dest);
//差集
_DestTy* set_difference(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _DestTy (&_Dest)[_DestSize], _Pr _Pred);
_DestTy* set_difference(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _DestTy (&_Dest)[_DestSize]);
_OutIt set_difference(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _OutIt _Dest, _Pr _Pred);
_OutIt set_difference(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _OutIt _Dest);
//遍历
_Fn for_each(_InIt _First, _InIt _Last, _Fn _Func);
//遍历并修改
_DestTy* transform(const _InIt _First, const _InIt _Last, _DestTy (&_Dest)[_DestSize], _Fn _Func);
_OutIt transform(const _InIt _First, const _InIt _Last, _OutIt _Dest, _Fn _Func);
_DestTy* transform(const _InIt1 _First1, const _InIt1 _Last1, _InIt2 _First2, _DestTy (&_Dest)[_DestSize], _Fn _Func);
_OutIt transform(const _InIt1 _First1, const _InIt1 _Last1, const _InIt2 _First2, _OutIt _Dest, _Fn _Func);
_DestTy* transform(const _InIt1 _First1, const _InIt1 _Last1, _RightTy (&_First2)[_RightSize], _DestTy (&_Dest)[_DestSize], _Fn _Func);
_OutIt transform(const _InIt1 _First1, const _InIt1 _Last1, _RightTy (&_First2)[_RightSize], const _OutIt _Dest, _Fn _Func);