【STL实用技巧】常用容器及相关问题和成员函数整理
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);
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)区间内数据 //该函数有多个重载
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);
stack
栈,后进先出。
stack.push(e); //入栈
stack.pop(); //出栈
stack.top(); //返回栈顶元素
stack.size(); //栈大小
stack.empty(); //栈判空
queue
queue队列,先进先出,固定一端进一端出,队尾进,队头出。priority_queue 是优先级队列。
queue.push(e); //往队尾添加元素
queue.pop(); //弹出队头的元素
queue.back();
queue.front();
queue.empty();
queue.size();
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(); //反转链表
set
集合容器,元素唯一且按一定规则有序排列,关于set排序功能的实现和函数对象可以参考本人这篇博客
multi_set 同一值可以出现多次。
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);
区别与相同点
1. 区别
vector | stack | queue | deque | list | set | multi_set | map | multi_map | |
数据结构 | 单端 数组 | 栈 | 队列 | 双端 数组 | 双向链表 | 二叉树 | 二叉树 | 二叉树 | 二叉树 |
随机访问 | 支持 | 不支持 | 不支持 | 支持 | 不支持 | 不支持 | 不支持 | 对key支持 | 不支持 |
2. 相同点
所有容器提供的都是值语意(value),而不是引用语意(reference)。也就是说向容器中插入元素时,实行的是拷贝行为。所以,向容器中装入元素时必须保证元素能够被拷贝(必须提供拷贝构造函数实现深拷贝)。