C++ |标准模板库STL

Vector

vector是线性容器,可叫做“变长数组”,即“长度可根据需要而自动改变的数组”调整存储空间大小。它的元素存储在一块连续的存储空间中,可以使用迭代器iterator和指针的偏移地址访问元素。

1.vector的定义

单独定义一个vector:vector<typename> name;
这个定义相当于是一维数组name[SIZE],不过长度可以根据需要进行变化,比较节省空间。
typename可以是任何基本类型,例如int,double、char、结构体等,也可以是STL标准容器,例如vector、set、queue等。
如果typename是vector,可以按下面这样定义:
vector<vector<int> > name;

2.vector容器内元素的访问

(1)通过下标访问
和访问普通数组是一样,对一个定义为vector vec的vector容器来说,直接访问vec[index](如vec[0]、vec[1]),这里的下标是从0到vec.siz()-1.
(2)通过迭代器访问
迭代器(iterator)定义:
vector<typename>::iterator it;
可以将迭代器理解为一种类似指针的东西。
可通过类似下表和指针访问数组的方式来访问容器内的元素:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include<cstdio>
#include<vector>
using namespace std;
int main()
{
vector<int> vec;
for(int i=1;i<=5;i++)
{
vec.push_back(i);
}
vector<int>::iterator it=vec.begin();//vec.begin()为取vec的首元素地址,it指向这个地址
/* 另一种遍历vector中元素的写法:
for(vector<int>::iterator it=vec.begin();it!=vec.end();it++)
*/
for(int i=0;i<5;i++)
{
printf("%d ",*(it+i));
}
return 0;
}siz

vec[i]和*(vec.begin()+i)是等价的。

3.vector常用函数
  1. push_back(x),在vector后面添加一个元素x。
  2. pop_back(),删除vector的尾元素。
  3. size(),获取vector中元素的个数
  4. clear(),清空vector中的所有元素,时间复杂度为O(N),其中N为vector中元素的个数。
  5. insert(),插入元素到某个位置中,insert(iterator loc,x)用来向vector的指定位置loc前插入一个元素x。
  6. erase(),有两种用法:删除单个元素,删除一个区间内的所有元素。erase(it)删除迭代器为it处的元素,earse(first,last)删除[first,last)内的所有元素。
    empty(),表示判断vector是否为空,如果为空,则返回true.
    容器的大小和容器的容量是有区别的,大小 是指元素的个数,容量是分配的内存大小,容量一般不小于容器的大小。vector::size()返回容器的大小,vector::capacity()返回容量值。
    vector的特点如下:
  • 随机访问元素效率很高
  • push_back的效率也会很高
  • push_front的效率非常低,不建议使用
  • vector在末尾添加和删除元素相对较好,而在其他位置添加和删除元素则不及其他顺序容器,在迭代器和引用也没有list支持的好

String

  1. string的定义
    定义string的方式跟基本数据类型相同,只需要在stirng后面跟上变量名,string str;,初始化可以海子街给string类型的变量赋值。
    string str="abcd";

  2. string中内容的访问:
    (1)可以直接通过下标访问,str[i]
    (2)通过迭代器访问,string::iterator it;

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #include<iostream>
    #include<string>
    using namespace std;
    int main()
    {
    string str="abcd";
    for(string::iterator it=str.begin();it!=str.end();it++)
    {
    cout<<*it;
    }
    return 0;
    }

    string和vector一样,可以直接对迭代器进行加减某个数字,如str.begin()+3

  3. 常用函数实例

  4. 两个string可以直接通过+拼接起来。

  5. 两个string类型可以直接使用==、!=、<、<=、>、>=比较大小,比较规则是字典序。(比较两个字符串对应的ASCII码值)

  6. length()/size(),length()返回string的长度,即存放的字符数,时间复杂度为O(1)。

  7. insert()

  8. erase()
    两种用法:删除单个元素,删除一个区间内的所有元素。
    str.erase(it)用于删除单个元素,it为需要删除的元素的迭代器。

string类的构造函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
string str:生成空字符串

string s(str):生成字符串为str的复制品

string s(str, strbegin,strlen):将字符串str中从下标strbegin开始、长度为strlen的部分作为字符串初值

string s(cstr, char_len):以C_string类型cstr的前char_len个字符串作为字符串s的初值

string s(num ,c):生成num个c字符的字符串

string s(str, stridx):将字符串str中从下标stridx开始到字符串结束的位置作为字符串初值

eg:


string str1; //生成空字符串
string str2("123456789"); //生成"1234456789"的复制品
string str3("12345", 0, 3);//结果为"123"
string str4("012345", 5); //结果为"01234"
string str5(5, '1'); //结果为"11111"
string str6(str2, 2); //结果为"3456789"

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str1; //生成空字符串
string str2("123456789"); //生成"1234456789"的复制品
string str3("12345", 0, 3);//结果为"123"
string str4("0123456", 5); //结果为"01234"
string str5(5, '1'); //结果为"11111"
string str6(str2, 2); //结果为"3456789"
cout<<"str2:"<<str2<<endl;
cout<<"str3:"<<str3<<endl;
cout<<"str4:"<<str4<<endl;
cout<<"str5:"<<str5<<endl;
cout<<"str6:"<<str6<<endl;
return 0;
}

输出结果:
在这里插入图片描述

string的大小和容量
  1. size()和length():返回string对象的字符个数,它们执行效果相同。
  2. max_size():返回string对象最多包含的字符数,超出会抛出length_error异常
  3. capacity():重新分配内存之前,string对象能包含的最大字符数
string的大小写转换:tolower()和toupper()函数 或者 STL中的transform算法

方法一:使用C语言的函数,进行转换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
#include <string>
using namespace std;

int main()
{
string str = "ABCDEFG";

for( int i = 0; i < str.size(); i++ )
{
str[i] = tolower(str[i]);
}

cout<<str<<endl;
return 0;
}
to_string 将数值转换为字符串,返回对应的字符串
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>   
#include <string>
using namespace std;

int main ()
{
string pi = "pi is " + std::to_string(3.1415926);
string perfect = std::to_string(1+2+4+7+14) + " is a perfect number";
cout << pi << '\n';
cout << perfect << '\n';
return 0;
}

结果:
pi is 3.141593
28 is a perfect number

set

set,是一个内部自动有序且不含重复元素的容器。set作为一个容器是用来存储同一数据类型的数据类型,并且能从一个数据结合中取出数据,在set中每个元素的值都是唯一的,

set常用函数实例
1.insert(x)
可将x插入set容器中,并自动递增排序和去重,时间复杂度为O(logN),其中N为set内的元素个数。
2.find()
find(value)返回set中对应值为value的迭代器,时间复杂度为O(logN),N为set内的元素个数。
3.erase()

  • 删除单个元素:
    st.erase(it),it为需要删除元素的迭代器,时间复杂度为O(1)。可结合find()函数一起使用
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    #include<iostream>
    #include<set>
    using namespace std;
    int main()
    {
    set<int> st;
    st.insert(100);
    st.insert(200);
    st.insert(100);
    st.insert(300);
    st.erase(st.find(100));//先利用find()函数找到100,然后用erase删除它
    st.erase(st.find(200));
    for(set<int>::iterator it=st.begin();it!=st.end();it++)
    {
    cout<<*it;
    }
    return 0;
    }
    st.erase(value),其中value为需要删除元素的值。时间复杂度为O(logN)。
  • 删除一个区间内的所有元素
    st.erase(first,last)可以删除一个区间内的所有元素,其中first为所需要删除区间的起始迭代器,last为待删除区间的末尾迭代器的下一个地址,即为删除[first,last].
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include<iostream>
#include<set>
using namespace std;
int main()
{
set<int> st;
st.insert(20);
st.insert(10);
st.insert(40);
st.insert(30);
set<int>::iterator it=st.find(30);
st.erase(it,st.end()); //删除元素30至set末尾之间的元素,即30和40
for(set<int>::iterator it=st.begin();it!=st.end();it++)
{
cout<<*it<<' ';
}
return 0;
}

4.size()
用来获取set内元素的个数,时间复杂度为O(1)。
5. clear()
清空set内的所有元素,复杂度为O(N),其中N为set内元素的个数

map

map本质是一个关联式容器,它提供一对一的hash。里面的数据都是成对出现的:

  • 每一对中的第一个值称为关键字(key),每个关键字只能在map中出现一次;
  • 第二个称为该关键字的值(value)。
    map以模板(泛型)方式实现,可以存储任意类型的数据,包括使用者自定义的数据类型。map主要用于资料一对一映射(one-to-one)的情況,map內部的实现自建一颗红黑树(一种非严格意义上的平衡二叉树),这颗树具有对数据自动排序的功能。在map内部所有的数据都是有序的,后边我们会见识到有序的好处。
    map可自动简历key-value的一一对应关系,比如一个班级中,每个学生的学号跟他的姓名就存在着一一映射的关系。

1.插入元素
map的插入有3种方式:用insert函数插入pair数据,用insert函数插入value_type数据和用数组方式插入数据。
第一种:用insert函数插入pair数据

1
2
map<int, string> mapStudent;
mapStudent.insert(pair<int, string>(1,“student_one”));

第二种:用insert函数插入value_type数据

1
2
map<int, string> mapStudent;
mapStudent.insert(map<int, string>::value_type (1,"student_one"));

用make_pair

1
mapStudent.insert(make_pair(1, "student_one"));

第三种:用数组方式插入数据

1
2
3
map<int, string> mapStudent;
mapStudent[1] = “student_one”;
mapStudent[2] = “student_two”;

以上四种用法,虽然都可以实现数据的插入,但是它们是有区别的,当然了第一种和第二种在效果上是完成一样的,用insert函数插入数据,在数据的插入上涉及到集合的唯一性这个概念,即当map中有这个关键字时,insert操作是不能再插入这个数据的,但是用数组方式就不同了,它可以覆盖以前该关键字对应的值,即:如果当前存在该关键字,则覆盖改关键字的值,否则,以改关键字新建一个key—value;
2.查找元素
用find函数来定位数据出现位置,它返回的一个迭代器,当所查找的关键字key出现时,它返回数据所在对象的位置,如果沒有,返回迭代器等于end函数返回的迭代器。

1
2
3
4
5
6
7
8
// find 返回迭代器指向当前查找元素的位置否则返回map::end()位置
iter = mapStudent.find("123456");

if(iter != mapStudent.end())
cout<<"Find, the value is"<<iter->second<<endl;
else
cout<<"Do not Find"<<endl;

3.删除与清空元素

1
2
3
4
5
6
7
8
9
10
//迭代器刪除
iter = mapStudent.find("123");
mapStudent.erase(iter);

//用关键字刪除
int n = mapStudent.erase("123"); //如果刪除了会返回1,否则返回0

//用迭代器范围刪除 : 把整个map清空
mapStudent.erase(mapStudent.begin(), mapStudent.end());
//等同于mapStudent.clear()

4.map的大小
在往map里面插入了数据,我们怎么知道当前已经插入了多少数据呢,可以用size函数,用法如下:
int nSize = mapStudent.size();
5.map的基本操作函数
C++ maps是一种关联式容器,包含“关键字/值”对

begin() 返回指向map头部的迭代器

clear() 删除所有元素

count() 返回指定元素出现的次数

empty() 如果map为空则返回true

end() 返回指向map末尾的迭代器

equal_range() 返回特殊条目的迭代器对

erase() 删除一个元素

find() 查找一个元素

get_allocator() 返回map的配置器

insert() 插入元素

key_comp() 返回比较元素key的函数

lower_bound() 返回键值>=给定元素的第一个位置

max_size() 返回可以容纳的最大元素个数

rbegin() 返回一个指向map尾部的逆向迭代器

rend() 返回一个指向map头部的逆向迭代器

size() 返回map中元素的个数

swap() 交换两个map

upper_bound() 返回键值>给定元素的第一个位置

value_comp() 返回比较元素value的函数