常用的STL容器
容器就是类模板,大致分为顺序容器,适配器容器和关联容器
顺序容器(vector,string deque,list)
关联容器(set(集合容器)/multlist(多重集合容器)),(map(映射容器)/multimap(多重映射容器))
适配器容器(stack(栈容器)/queue(队列容器)/priority_queue(优先队列容器))
一,顺序容器
vector(向量容器)
- 优点:可以从末尾快速地插入与删除元素,快速的随机访问元素
- 缺点:在序列中间插入,删除元素较慢,因为需要移动插入或删除位置后面的所有元素
//vector主要成员函数
vector<int> v1{10,2};
empty()://判断当前向量容器是否为空
size()://返回当前向量容器中的实际元素个数
[]://返回指定下标的元素
reserve(n)://为当前向量容器预分配n个元素的存储空间
capacity()://返回当前向量容器在重新进行内存分配以前所能容纳的元素个数
resize(n)://调整当前向量容器的大小,使其能容纳n个元素
push_back(item)://在当前向量容器尾部添加一个元素
insert(pos,elem)://在pos位置插入元素elem,即将元素elem插入到迭代器pos指定的元素之前
front()://获取当前向量容器的第一个元素
back()://获取当前向量容器的最后一个元素
erase()://删除当前向量容器中某个迭代器或者迭代器区间指定的元素
clear()://删除当前向量容器中的所有元素
begin()://该函数的两个版本分别返回iterator或者const_iterator,引用容器的第一个元素
end()://该函数的两个版本分别返回iterator或者const_iterator,引用容器的最后一个元素后面的一个位置
rbegin()://该函数的两个版本分别返回reverse_iterator或者const_reverse_iterator,引用容器的最后一个元素
rend()://该函数的两个版本分别返回reverse_iterator或者const_reverse_iterator,引用容器的第一个元素前面的第一个位置
如:
int main() {
myv.push_back(1);
myv.push_back(2);
myv.push_back(3);
// 正向输出所有元素
vector<int>::iterator it;
myv.insert(myv.begin(), 0);
for (it = myv.begin(); it != myv.end(); ++it)
{
cout << *it << endl;
}
// 反向输出所有元素
vector<int>::reverse_iterator it1;
for (it1 = myv.rbegin(); it1 != myv.rend(); it1++)
{
cout << *it1 << endl;
}
return 0;
}
string(字符串容器)
string是一个保存字符序列的容器,它的所有元素为字符类型,类似vector,因此除了有字符串的一些常用操作外,还包含了所有序列容器的操作,字符串的常用操作包括增加,删除,修改,查找,比较,连接,输入,输出等,string重载了许多运算符,包括+,+=,<,=,[],<<和>>等,
// 创建string容器的几种方式
string()://创建一个空的字符串
string(const string& str)://用字符串str建立当前字符串
string(const string& str,size_type str_idx)://用字符串str起始于str_idx的字符建立当前字符串
string(const string& str,size_type str_idx,size_type str_num)://用字符串str起始于str_idx的str_num个字符建立当前字符串
string(const char* cstr)://用C-字符串cstr建立当前字符串
string(const char* chars,size_type chars_len)://用C-字符串cstr开头的chars_len个字符建立当前字符串
string(size_type num,char c)://用num个字符c建立当前字符串
例如:
char cstr[] = "China! Greate Wall";
string s1(cstr); // China! Greate Wall
string s2(s1); // China! Greate Wall
string s3(cstr,7,11); // Grate Wall
string s4(cstr,6); // China!l
string s5(5,'A'); // AAAAA
//string常用函数(size_type在不同的机器上长度是可以不同的,并非固定的长度,一般通常size_type为ungisned int类型)
empty()://判断当前字符串是否为空串
size()://返回当前字符串的实际字符个数(返回结果为size_type类型)
length()://返回当前字符串的实际字符个数
[index]://返回当前字符串位于index位置的字符,index从0开始
s(index)://返回当前字符串位于index位置的字符
compare(const string& str)://返回当前字符串与字符串str的比较结果,在比较时,若两者相等,返回0,若前者小于后者返回-1,否则返回1
append(cstr)://在当前字符串的末尾添加一个字符串str
insert(size_type index,const string & str)://在当前字符串的index处插入一个字符串str
find(string& s,size_type pos)://从当前字符串中的pos位置开始查找字符串s的第一个位置,找到后返回其位置,没有找到返回-1
replace(size_type index,size_type len,const string& str)://将当前字符串中起始于index的len个字符用一个字符串str替换
replace(iterator begin,iterator end,const string& str)://将当前字符串中由迭代器begin和end所指区间的所有字符用一个字符串替换
substr(size_type index);//返回当前字符串起始于index的子串
substr(size_type index,size_type len)://返回当前字符串起始于index的长度为len的子串
clear()://删除当前字符串中的所有字符
erase()://删除当前字符串中所有字符
erase(size_type index)://删除当前字符串从index开始的所有字符
erase(size_type index,size_type len)://删除当前字符串从index开始的len个字符
deque(双端队列容器)
1,是双端队列类模板,双端队列容器由若干个块构成,每个块中的元素的地址是连续的,但是块的地址是不连续的,
2,可以从前面或后面快速的插入与删除元素,并可以快速地随机访问元素,但在中间位置插入和删除元素速度较慢
3,deque容器不像vector那样把所有的元素保存在一个连续的内存块,而是采用多个连续的存储块存放数据元素,所以空间的重新分配要比vector快,因为重新分配空间后原有的元素不需要复制
// 定义deque双端队列容器的几种方式
deque<int> dp1; // 定义元素为int的双端队列dp1
deque<int> dp2(10); // 指定dp2的初始大小为10个int元素
deque<double> dq3(10,1.23); // 指定dq3的10个初始元素的初始值为1.23
deque<int> dp4(dp2.begin(),dp2.end()) // 用dp2的所有元素初始化dp4
// deque常用函数
empty()://判断双端队列容器是否为空队
size()://返回双端队列容器中的元素个数
front()://取队头元素
back()://取队尾元素
push_front(elem)://在队头插入元素elem
push_back(elem)://在队尾插入元素elem
pop_front()://删除队头一个元素
pop_back()://删除队尾一个元素
erase()://从双端队列容器中删除一个或几个元素
clear()://删除双端队列容器中的所有元素
begin()://该函数的两个版本返回iterator或const_iterator,引用容器的第一个元素
end()://该函数的两个版本返回iterator或const_iterator,引用容器的最后一个元素后面的一个位置
rbegin()://该函数的两个版本返回reverse_iterator或const_reverse_iterator,引用容器的最后一个元素
rend()://该函数的两个版本返回reverse_iterator或const_reverse_iterator,引用容器的第一个元素前面的一个位置
void disp(deque<int> &dp){
deque<int>::iterator iter;
for (iter = myv.begin(); it != myv.end(); ++it)
{
cout << *it << endl;
}
}
deque<int> dp;
dp.push_front(1); // 插入队头
dp.push_back(2);// 插入队尾
list(链表容器)
list是双链表类模板,它的每个结点之间通过指针链接,不能随机访问元素,为了访问表容器中特定的元素,必须从第一个位置开始,随着指针从一个到下一个元素,直到找到要找的元素,list容器插入元素比vector快,对每个元素单独分配空间,所以不存在空间不够需要重新分配的情况
// 定义list容器的几种方式
list<int> l1; // 定义元素为int的链表l1
list<int> l2(10); // 指定链表l2的初始大小为10个int元素
list<double> l3(10,1.23); // 指定l3的10个初始元素的初值为1.23
list<int> l4(a,a+5); // 用数组a[0...4]共5个元素初始化l4
empty()://判断链表容器是否为空
size()://返回链表容器中的实际元素个数
push_back(elem)://在链尾尾部插入元素elem
pop_back()://删除链表容器最后一个元素
remove()://删除链表容器中所有指定值的元素
remove_if(cmp)://删除链表容器中满足条件的元素
erase()://从链表容器中删除一个或几个元素
unique()://删除链表容器中相邻的重复元素
clear()://删除链表容器中的所有元素
insert(pos,elem)://在pos位置插入元素elem,即将元素elem插入到迭代器pos指定的元素之前
insert(pos,n,elem)://在pos位置插入n个元素elem
insert(pos,pos1,pos2)://在迭代器pos处插入[pos1,pos2)的元素 lst.inset(it,start,end)
reverse()://反转链表
sort()://对链表容器中的元素排序
begin()://该函数的两个版本返回iterator或const_iterator,引用容器的第一个元素
end()://该函数的两个版本返回iterator或const_iterator,引用容器的最后一个元素后面的一个位置
rbegin()://该函数的两个版本返回reverse_iterator或const_reverse_iterator,引用容器的最后一个元素
rend()://该函数的两个版本返回reverse_iterator或const_reverse_iterator,引用容器的第一个元素前面的一个位置
void disp(list<int> &dp){
list<int>::iterator iter;
for (iter = lst.begin(); it != lst.end(); ++it)
{
cout << *it << endl;
}
}
需要注意的是:STL提供的sort()排序算法主要用于支持随机访问的容器,而list容器不支持随机访问,为此list容器提供了sort()成员函数用于元素排序,类似的还有unique(),reverse(),merge()等STL算法
二,关联容器
关联容器中的每个元素有一个key(关键字),通过key来存储和读取元素,这些关键字可能与元素在容器中的位置无关,
所以关联容器不提供顺序容器中的front(),push_front(),back(),push_back()以及pop_back()操作,
set(集合容器)/multiset(多重集合容器)
set和multiset都是集合类模板,其元素值称为关键字,set中元素的关键字是唯一的,multiset中元素的关键字可以不唯一,而且默认情况下会对元素按关键字自动进行升序排列,所以查找速度比较快,同时支持交,差,并等集合上的运算,如果需要集合中的元素允许重复,那么使用multiset
set中没有相同关键字的元素,在向set中插入元素时,如果已经存在则不插入,multiset中允许存在两个相同关键字的元素,在删除操作时删除multiset中值等于elem的所有元素,若删除成功返回删除个数,否则返回0
// set/multiset常用成员函数
empty()://判断容器是否为空
size()://返回容器中的实际元素个数
insert()://插入元素
erase()://从容器中删除一个或几个元素
clear()://删除所有元素
count(k)://返回容器中关键字k出现的次数
find(k)://如果容器中存在关键字为k的元素,返回该元素的迭代器,否则返回end()值
upper_bound()://返回一个迭代器,指向关键字大于k的第一个元素
lower_bound()://返回一个迭代器,指向关键字不小于k的第一个元素
begin()://用于正向迭代,返回容器的第一个元素
end()://用于正向迭代,返回容器的最后一个元素后面的一个位置
rbegin()://用于反向迭代,返回容器的最后一个元素的位置
rend()://用于反向迭代,返回容器的第一个元素前面的一个位置
map(映射容器)/multimap(多重映射容器)
1,map和multimap都是映射类模板,映射是实现关键字与值关系的存储结构,可以使用一个关键字key来访问相应的数据值value,set/multimap中的key和value都是key类型,而map/multimap中的key和value是一个pair类结构,
//pair类结构的声明形式如下:
struct pair{
T first;
T second;
}
// pair中的first为第一个分量(在map中对应key),second为第二个分量(在map中对应value)
pair <double,double> p1; // 定义pair对象p1
cin >> p1.first >> p1.second;
// 同时pair对==,!=,<,>,<=,>=共六个运算符进行重载,提供了按照字典序对元素进行大小比较的比较运算符模板函数
// map/multimap的主要成员函数如下
empty()://判断容器是否为空
size()://返回容器中的实际元素个数
map[key]://返回关键字为key的元素的引用,如果不存在这样的关键字,则以key作为关键字插入一个元素(不适合multimap)
insert(elem)://插入一个元素elem并返回该元素的位置
clear()://删除所有元素
find()://在容器中查找元素
count()://容器中指定关键字的元素个数(map中只有1或者0)
begin()://用于正向迭代,返回容器中的第一个元素位置
end()://用于正向迭代,返回容器中最后一个元素的位置
rbegin()://用于反向迭代,返回容器中最后一个元素的位置
rend()://用于反向迭代,返回容器中第一个元素前面的一个位置
// 在map中修改元素
map<char,int> mymap;
mymap['a'] = 1;
// 获取map中的值
int ans = mymap['a'];
#include<map>
map<char, int> mymap;
mymap['a'] = 3;
map<char, int>::iterator it;
for (it = mymap.begin(); it != mymap.end(), ++it) {
cout << it->first, it->second;
}
三,适配器容器
适配器容器是指基于其他容器实现的容器,也就是说适配器容器包含另一个容器作为其底层容器,在底层容器的基础上实现适配器容器的功能,实际上在算法设计中可以将适配器容器作为一般容器来使用
stack(栈容器)
C++栈和数据结构中的栈一样,具有后进先出的特点,栈容器默认的底层容器是deque,用户也可以指定其他底层容器,
stack<string,vector<string>> myst; //第二个参数指定底层容器为vector
stack容器只有一个出口,即栈顶,可以在栈顶插入(进栈)和删除(出栈)元素,而不允许顺序遍历,所以stack容器没begin()/end()/rbegin()/rend()迭代器成员函数,stack容器的主要成员为:
empty()://判断栈容器是否为空
size()://返回栈容器中的实际元素个数
push(elem)://元素elem进栈
top()://返回栈顶元素
pop()://元素出栈
#include<stack>
using namespace std;
void main(){
stack<int> st;
st.push(1);st.push(2);st.push(3);
cout << st.top() << endl;
while(!st.empty()){
cout << st.pop() <<endl;
st.pop();
}
}
queue(队列容器)
1,队列类模板,和数据结构中的队列一样,具有先进先出的特点,queue容器不允许顺序遍历,没有begin()/end()和rbegin()/rend()这样的用于迭代器的成员函数,
// 主要成员函数如下:
empty()://判断队列容器是否为空
size()://返回队列容器中的实际元素个数
front()://返回队头元素
back()://返回队尾元素
push(elem)://元素elem进队
pop()://元素出队
#include<queue>
using namespace std;
void main(){
queue<int> qu;
qu.push(1);qu.push(2);qu.push(3);
cout << "队头元素" << qu.front();
cout << "队尾元素" << qu.back();
while(!qu.empty()){
cout << qu.front() << endl;
qu.pop();
}
}
priority_queue(优先队列容器)
优先队列是一种具有受限访问操作的存储结构,元素可以以任意顺序进入优先队列,一旦元素在优先队列容器中,出队操作将出队列中优先级最高的元素,
// 主要成员函数
empty()://判断优先队列容器是否为空
size()://返回优先队列容器中的实际元素个数
push(elem)://元素elem进队
top()://获取队头元素
pop()://元素出队
// 优先队列中优先级的高低由队列中数据元素的关系函数(比较运算符)确定,用户可以使用默认的关系函数(对于内置数据类型,默认关系函数是值越大优先级越高),也可以重载自己编写的关系函数
#include<queue>
using namespace std;
void main(){
priority_queue<int> qu;
qu.push(3);qu.push(1);qu.push(2);
cout << qu.top() << "队头元素" << endl;
qu.pop();
}