C/C++学习笔记——标准模板库

容器

所有容器都有以下两个成员函数:

成员函数说明
int size()返回容器对象中元素的个数。
bool empty():判断容器对象是否为空。

顺序容器和关联容器还有以下成员函数:

成员函数说明
begin()返回指向容器中第一个元素的迭代器。
end()返回指向容器中最后一个元素后面的位置的迭代器。
rbegin()返回指向容器中最后一个元素的反向迭代器。
rend()返回指向容器中第一个元素前面的位置的反向迭代器。
erase(…)从容器中删除一个或几个元素。该函数参数较复杂,此处省略。
clear()从容器中删除所有元素。

如果一个容器是空的,则 begin() 和 end() 的返回值相等,rbegin() 和 rend() 的返回值也相等。

顺序容器还有以下常用成员函数:

成员函数说明
front()返回容器中第一个元素的引用。
back()返回容器中最后一个元素的引用。
push_back()在容器末尾增加新元素。
pop_back()删除容器末尾的元素。
insert(…)插入一个或多个元素。该函数参数较复杂,此处省略。

顺序容器

可变长数组vector(< vector >)

  • vector 是可变长的动态数组,支持随机访问迭代器,所有 STL 算法都能对 vector 进行操作。
  • 在 vector 容器中,根据下标随机访问某个元素的时间是常数,在尾部添加一个元素的时间大多数情况下也是常数,总体来说速度很快。
  • 在中间插入或删除元素时,因为要移动多个元素,因此速度较慢,平均花费的时间和容器中的元素个数成正比。
  • 在 vector 容器中,用一个动态分配的数组来存放元素,因此根据下标访问某个元素的时间是固定的,与元素个数无关。
  • vector 容器在实现时,动态分配的存储空间一般都大于存放元素所需的空间。例如,哪怕容器中只有一个元素,也会分配 32 个元素的存储空间。这样做的好处是,在尾部添加一个新元素时不必重新分配空间,直接将新元素写入适当位置即可。在这种情况下,添加新元素的时间也是常数。
  • 如果空间用完,此时再添加新元素,就不得不重新分配内存空间,把原有内容复制过去后再添加新的元素。碰到这种情况,添加新元素所花的时间就不是常数,而是和数组中的元素个数成正比。
  • 在中间插入或删除元素,必然涉及元素的移动,因此时间不是固定的,而是和元素个数有关。

定义和初始化vector对象

格式作用
vector<T> v1v1是一个空vector,它潜在的元素是T类型的,执行默认初始化
vector<T> v2(v1)v2中包含有v1所有元素的副本
vector<T> v2 = v1等价于v2(v1),v2中包含有v1所有元素的副本
vector<T> v3(n, val)v3包含了n个重复的元素,每个元素的值都是val
vector<T> v4(n)v4包含了n个重复地执行了值初始化的对象
vector<T> v5{a,b,c...}v5包含了初始值个数的元素,每个元素被赋予相应的初始值
vector<T> v5={a,b,c...}等价于v5{a,b,c…}

注意(){}用法的区别
vector成员函数

成员函数作 用
vector()无参构造函数,将容器初始化为空
vector(int n)将容器初始化为有 n 个元素
vector(int n, const T & val)假定元素的类型是 T,此构造函数将容器初始化为有 n 个元素,每 个元素的值都是 val
vector(iterator first, iterator last)first 和 last 可以是其他容器的迭代器。一般来说,本构造函数初始化的结果就是将 vector 容器的内容变成与其他容器上的区间 [first, last) —致
void clear()删除所有元素
bool empty()判断容器是否为空
void pop_back()删除容器末尾的元素
void push_back( const T & val)将 val 添加到容器末尾
int size()返回容器中元素的个数
T & front()返回容器中第一个元素的引用
T & back()返回容器中最后一个元素的引用
iterator insert(iterator i, const T & val)将 val 插入迭代器 i 指向的位置,返回 i
iterator insert( iterator i, iterator first, iterator last)将其他容器上的区间 [first, last) 中的元素插入迭代器 i 指向的位置
iterator erase(iterator i)删除迭代器 i 指向的元素,返回值是被删元素后面的元素的迭代器
iterator erase(iterator first, iterator last)删除容器中的区间 [first, last)
void swap( vector & v)将容器自身的内容和另一个同类型的容器 v 互换

双向链表list(< list >)

List构造方法:

格式作用
list c0空链表
list c1(n)建一个含n个默认值是0的元素的链表
list c2(n,m)建一个含n个元素的链表,值都是m
list c4(c2)建一个c2的copy链表
list c5(c1.begin(),c1.end())c5含c1一个区域的元素[_First, _Last)。

list部分成员函数与vector相同。
List其它成员函数:

成员函数说明
void push_front(const T & val)将 val 插入链表最前面
void pop_front()删除链表最前面的元素
void sort()将链表从小到大排序
void remove (const T & val)删除和 val 相等的元素
remove_if删除符合某种条件的元素
void unique()删除所有和前一个元素相等的元素
void merge(list & x)将链表 x 合并进来并清空 x。要求链表自身和 x 都是有序的
void splice(iterator i, list & x, iterator first, iterator last)在位置 i 前面插入链表 x 中的区间 [first, last),并在链表 x 中删除该区间。链表自身和链表 x 可以是同一个链表,只要 i 不在 [first, last) 中即可

双向队列deque(< deque >)

所有适用于 vector 的操作都适用于 deque。
它有两种 vector 没有的成员函数:

成员函数说明
void push_front (const T & val)将 val 插入容器的头部
void pop_front()删除容器头部的元素

关联容器

关联容器有以下四种。

容器说明
set排好序的集合,不允许有相同元素。
multiset排好序的集合,允许有相同元素。
map每个元素都分为关键字和值两部分,容器中的元素是按关键字排序的。不允许有多个元素的关键字相同。
multimap和 map 类似,差别在于元素的关键字可以相同。

不能修改关联容器中元素的值。因为元素被修改后,容器并不会自动重新调整顺序,于是容器的有序性就会被破坏,再在其上进行查找等操作就会得到错误的结果。因此,如果要修改 容器中某个元素的值,正确的做法是先删除该元素,再插入新元素。
除了所有容器共有的成员函数外,关联容器还具有以下成员函数:

成员函数说明
find查找某个值。
lower_bound查找某个下界。
upper_bound查找某个上界。
equal_range同时查找上界和下界。
count计算等于某个值的元素个数。
insert插人一个元素或一个区间。

multiset(< set >)

multiset 类模板的定义如下:

template <class Key, class Pred = less<Key>, class B = allocator<Key> > class multiset 
{...};

multiset 的部分成员函数

成员函数或成员函数模板作 用
iterator find (const T & val);在容器中查找值为 val 的元素,返回其迭代器。如果找不到,返回 end()
iterator insert( const T & val);将 val 插入容器中并返回其迭代器
void insert(iterator first, iterator last);将区间 [first, last) 中的元素插人容器
int count( const T & val);统计有多少个元素的值和 val 相等
iterator lower_bound( const T & val);查找一个最大的位置 it,使得 [begin(), it) 中所有的元素者比 val 小
iterator upper_bound( const T & val);查找一个最小的位置 it,使得 [it, end()) 中所有的元素都比 val 大
pair <iterator, iterator > equal_range (const T & val);同时求得 lower_bound 和 upper_bound
iterator erase(iterator it);删除 it 指向的元素,返回其后面的元素的迭代器(Visual Studio 2010 中如此,但是在 C++ 标准和 Dev C++ 中,返回值不是这样)
iterator erase(iterator first, iterator last);删除区间 [first, last),返回 last(Visual Studio 2010 中如此,但是在 C++ 标准和 Dev C++ 中,返回值不是这样)

multiset 及 set 中的 find 和 count 并不是==运算符比较元素是否和待查找的值相等的。它们进行比较的原则是:如果x比y小y比x小同时为假,就认为 x 和 y 相等。

set(< set >)

set 是一种排序好的集合(元素已经进行了排序)。set 和 multiset 类似,它和 multiset 的差别在于 set 中不能有重复的元素。multiset 的成员函数 set 中也都有。
set 的定义如下:

template < class Key, class Pred = less<Key>, class A = allocator<Key> > class set
{...}

由于不能有重复元素,所以 set 中插入单个元素的 insert 成员函数与 multiset 中的有所不同,其原型如下:
pair<iterator, bool> insert(const T & val);
如果 set 的 insert 成员函数的返回值是 pair 模板类对象 x,如果 x.second 为 true,则说明插入成功,此时 x.first 就是指向被插入元素的迭代器;如果 x.second 为 false,则说明要插入的元素已在容器中,此时 x.first 就是指向原有那个元素的迭代器。

关联容器的 equal_range 成员函数的返回值也是 pair 模板类对象,其原型如下:
pair<iterator, iterator> equal_range(const T & val);
返回值对象中的 first 就是 lower_bound 的值,second 就是 upper_bound 的值。

#include <iostream>
#include <set>  //使用set须包含此文件
using namespace std;
int main()
{
    typedef set<int>::iterator IT;
    int a[5] = { 3,4,6,1,2 };
    set<int> st(a,a+5);    // st里是 1 2 3 4 6
    pair< IT,bool> result;
    result = st.insert(5); // st变成  1 2 3 4 5 6
    if(result.second)    //插入成功则输出被插入元素
        cout << * result.first  << " inserted" << endl; //输出: 5 inserted
    if(st.insert(5).second)
        cout << * result.first  << endl;
    else
        cout << * result.first << " already exists" << endl;
    //输出 5 already exists
    pair<IT,IT> bounds = st.equal_range(4);
    cout << * bounds.first << "," << * bounds.second ;  //输出:4,5
    return 0;
}

程序的输出结果是:
5 inserted
5 already exists
4,5

multimap(< map >)

multimap 的定义如下:

template < class Key, class T, class Pred = less<Key>, class A = allocator<T> >
class multimap
{
    ...
    typedef pair <const Key, T> value_type;
    ...
};

multimap 中的元素都是 pair 模板类的对象。元素的 first 成员变量也叫“关键字”,second 成员变量也叫“值”。multimap 容器中的元素是按关键字从小到大排序的。默认情况下,元素的关键之间用 less <Key>比较大小,也就是用<运算符比较大小。multimap 允许多个元素的关键字相同。
multimap 中的 value_type 实际上就表示容器中元素的类型。C++ 允许在类的内部定义类型。

multimap 的部分成员函数

成员函数或成员函数模板作 用
iterator find( const Key & val);在容器中查找关键字等于 val 的元素,返回其迭代器;如果找不到,返回 end()
iterator insert (pair <Key, T> const &p);将 pair 对象 p 插入容器中并返回其迭代器
void insert(iterator first, iterator last);将区间 [first, last) 插入容器
int count( const Key & val);统计有多少个元素的关键字和 val 相等
iterator lower_bound( const Key & val);查找一个最大的位置 it,使得 [begin( ), it) 中所有的元素的关键字都比 val 小
iterator upper_bound(const Key & val);查找一个最小的位置 it,使得 [it, end()) 中所有的元素的关键字都比 val 大
pair < iterator, iterator > equal_range (const Key & val);同时求得 lower_bound 和 upper_bound
iterator erase(iterator it);删除 it 指向的元素,返回其后面的元素的迭代器(Visual Studio 2010 中如此,但是在 C++ 标准和 Dev C++ 中,返回值不是这样)
iterator erase(iterator first, iterator last);删除区间 [first, last),返回 last(Visual Studio 2010 中如此,但是在 C++ 标准和 Dev C++ 中,返回值不是这样)

map(< map >)

map 的定义如下:

template < class Key, class T, class Pred = less<Key>, class A = allocator<T> >
class map{
    ...
    typedef pair< const Key, T > value_type;
    ...
};

map 和 multimap 十分类似,区别在于 map 容器中元素的关键字不能重复。multimap 有的成员函数,map 都有。此外,map 还有成员函数 operator[]:T & operator[] (Key k);该成员函数返回 first 值为 k 的元素的 second 部分的引用。如果容器中没有元素的 first 值等于 k,则自动添加一个 first 值为 k 的元素。如果该元素的 second 成员变量是一个对象,则用无参构造函数对其初始化。

容器适配器

STL 中的容器适配器有 stack、queue、priority_queue 三种。它们都是在顺序容器的基础上实现的,屏蔽了顺序容器的一部分功能,突出或增加了另外一些功能。

容器适配器都有以下三个成员函数:

成员函数说明
push添加一个元素。
top返回顶部(对 stack 而言)或队头(对 queue、priority_queue 而言)的元素的引用。
pop删除一个元素。

容器适配器是没有迭代器的,因此 STL 中的各种排序、查找、变序等算法都不适用于容器适配器。

stack(< stack >)

stack就是“栈”。栈是一种后进先出的元素序列,访问和删除都只能对栈顶的元素(即最后一个被加入栈的元素)进行,并且元素也只能被添加到栈顶。栈内的元素不能访问。如果一定要访问栈内的元素,只能将其上方的元素全部从栈中删除,使之变成栈顶元素才可以。

成员函数功 能
void pop();弹出(即删除)栈顶元素
T & top();返回栈顶元素的引用。通过此函数可以读取栈顶元素的值,也可以修改栈顶元素
void push (const T & x);将 x 压入栈顶
bool empty()判断容器是否为空
int size()返回容器中元素的个数

queue和priority_queue(< queue >)

queue
queue 就是“队列”。队列是先进先出的,和排队类似。队头的访问和删除操作只能在队头进行,添加操作只能在队尾进行。不能访问队列中间的元素。
queue 可以用 list 和 deque 实现,默认情况下用 deque 实现。
queue 的定义如下:

template < class T, class Cont = deque<T> >
class queue{
    ...
};

queue 同样也有和 stack 类似的 push、pop、top 函数。区别在于,queue 的 push 发生在队尾,pop 和 top 发生在队头。

priority_queue
priority_queue 是“优先队列”。它和普通队列的区别在于,优先队列的队头元素总是最大的——即执行 pop 操作时,删除的总是最大的元素;执行 top 操作时,返回的是最大元素的引用。

priority_queue 可以用 vector 和 deque 实现,默认情况下用 vector 实现。

priority_queue 默认的元素比较器是 less 。也就是说,在默认情况下,要放入 priority_queue 的元素必须是能用<运算符进行比较的,而且 priority _queue 保证以下条件总是成立:对于队头的元素 x 和任意非队头的元素 y,表达式x<y必为 false。

priority_queue 定义如下:

template < class T, class Container = vector <T>, class Compare = less<T> >
class priority_queue{
    ...
};

priority_queue 的第三个类型参数可以用来指定排序规则。

和 set/multiset 不同,priority_queue 是使用“堆排序”技术实现的,其内部并非完全有序,但却能确保最大元素总在队头。因此,priority_queue 特别适用于“不停地在一堆元素中取走最大的元素”这种情况。priority_queue 插入和删除元素的复杂度都是 O(log(n))。虽然用 set/multiset 也能完成此项工作,但是 priority_queue 比它们略快一些。

priority_queue 队头的元素只能被查看或者修改,不能被删除。

迭代器

迭代器按照定义方式分成以下四种。

  • 正向迭代器,定义方法如下:
    容器类名::iterator 迭代器名;
  • 常量正向迭代器,定义方法如下:
    容器类名::const_iterator 迭代器名;
  • 反向迭代器,定义方法如下:
    容器类名::reverse_iterator 迭代器名;
  • 常量反向迭代器,定义方法如下:
    容器类名::const_reverse_iterator 迭代器名;

通过迭代器可以读取它指向的元素,*迭代器名就表示迭代器指向的元素。通过非常量迭代器还能修改其指向的元素。
正向迭代器进行++操作时,迭代器会指向容器中的后一个元素;而对反向迭代器进行++操作时,迭代器会指向容器中的前一个元素。

常用的迭代器按功能强弱分为输入、输出、正向、双向、随机访问五种,这里只介绍常用的三种。

  1. 正向迭代器。假设 p 是一个正向迭代器,则 p 支持以下操作:++pp++*p。此外,两个正向迭代器可以互相赋值,还可以用==!=运算符进行比较。
  2. 双向迭代器。双向迭代器具有正向迭代器的全部功能。除此之外,若 p 是一个双向迭代器,则--p和p–都是有定义的。--p使得 p 朝和++p相反的方向移动。双向迭代器。双向迭代器具有正向迭代器的全部功能。除此之外,若 p 是一个双向迭代器,则--pp--都是有定义的。--p使得 p 朝和++p相反的方向移动。
  3. 随机访问迭代器。随机访问迭代器具有双向迭代器的全部功能。若 p 是一个随机访问迭代器,i 是一个整型变量或常量,则 p 还支持以下操作:随机访问迭代器。随机访问迭代器具有双向迭代器的全部功能。若 p 是一个随机访问迭代器,i 是一个整型变量或常量,则 p 还支持以下操作:
    p+=i:使得 p 往后移动 i 个元素。
    p-=i:使得 p 往前移动 i 个元素。
    p+i:返回 p 后面第 i 个元素的迭代器。
    p-i:返回 p 前面第 i 个元素的迭代器。
    p[i]:返回 p 后面第 i 个元素的引用。

不同容器的迭代器的功能

容器迭代器功能
vector随机访问
deque随机访问
list双向
set / multiset双向
map / multimap双向
stack不支持迭代器
queue不支持迭代器
priority_queue不支持迭代器

string(< string >)

字符串类型,与c语言中不同string结尾没有结束标志\0
初始化string对象的方式

格式操作
string s1默认初始化,s1是一个空串
string s2(s1)s2是s1的副本
string s2 = s1等价string s2(s1)
string s3(“value”)s3是字面值“value”的副本,除了字面值最后的空格外
string s3 = “value”等价于string s3(“value”)
string s4(n,‘c’)把s4初始化为连续n个‘c’组成的串

使用=拷贝初始化,不使用是直接初始化

string s;
cin >> s ;
cout << s << endl;

输入" Hello World "时,string类型会忽视开始的空格,从第一个真正的字符开始,直到遇见下一个空格,输出为Hello

string的操作

格式操作
os>>s将s写到输出流os当中,返回os
is>>s从is中读取字符串赋给s,字符串以空白分隔,返回is
getline(is,s)从is中读取一行赋给s,返回is
s.empty()s为空返回true,否则返回false
s.size()返回s中字符的个数
s[n]返回s中第n个字符的引用,位置n从0计起
s1 + s2返回s1和s2连接后的结果
s1 = s2用s1的副本代替s1中原来的字符
s1 == s2如果s1和s2中所含的字符完全一样,则它们相等;string对象的相等性判断对字母的大小写敏感
s1 != s2如果s1和s2中所含的字符出现不一样,则它们相等;string对象的相等性判断对字母的大小写敏感
< , <= , > , >=利用字符在字典中的顺序进行比较,且对字母的大小写敏感
s.erase (pos,len)pos 表示要删除的子字符串的起始下标,len 表示要删除子字符串的长度。如果不指明 len 的话,那么直接删除从 pos 到字符串结束处的所有字符(此时 len = str.length - pos)
s.insert (pos,str)pos 表示要插入的位置,也就是下标;str 表示要插入的字符串,它可以是 string 字符串,也可以是C风格的字符串。
s.substr (pos, len)pos 为要提取的子字符串的起始下标,len 为要提取的子字符串的长度。
s1.find(s2,5)第一个参数为待查找的子字符串,它可以是 string 字符串,也可以是C风格的字符串。第二个参数为开始查找的位置(下标);如果不指明,则从第0个字符开始查找。
s1.rfind(s2,6)rfind() 和 find() 很类似,同样是在字符串中查找子字符串,不同的是 find() 函数从第二个参数开始往后查找,而 rfind() 函数则最多查找到第二个参数处,如果到了第二个参数所指定的下标还没有找到子字符串,则返回一个无穷大值4294967295。
s1.find_first_of(s2)find_first_of() 函数用于查找子字符串和字符串共同具有的字符在字符串中首次出现的位置。

使用+时,+两侧至少有一个为string对象,不能把字面值相加。

string str = "Hello";
string phrase= "Hello World";
string slang = "Hiya";

以上三个字符相比较,结果为:str < phrase slang > phrase slang > phrase。两字符串相比较,大小由不同位置的字符字典顺序决定;短字符串与长字符串前面部分完全相同时,短字符串较小。
cctype头文件中的函数

格式操作
isalnum(c)如果c是字母数字,即字母或数字,返回true
isalpha(c)如果c是字母,返回true
isblank(c)如果c是空格或水平制表符,返回true
iscntrl(c)如果c是控制字符,返回true
isdigit(c)如果c是数字,返回true
isgraph(c)如果c是除空格之外的打印字符,返回true
islower(c)如果c是小写字母,返回true
ispunct(c)如果c是标点符号,返回true
isspace(c)如果c是标准空白字符,如空格,进纸,换行符,回车,水平/垂直制表,返回true
isupper(c)如果c是大写字母,返回true
isxdigit(c)如果c是十六进制的数字,即0-9,A-F,a-f,返回true
tolower(c)返回c的小写形式
toupper(c)返回c的大写形式

string s;访问s中每个字符可以用for(auto c : s) //或for(char c : s)操作,如果要修改需要用引用for(auto &c : s){}操作,也可以用下标进行操作s[i]注意不要越界

bitset类

初始化:bitset <40> bst; bst 是一个由 40 个位组成的对象,用 bitset 的成员函数可以方便地访问其中任意一位。bitset 中的位从 0 开始编号,第 0 位是最右边的位。

bitset 有许多成员函数,有些成员函数执行的就是类似于位运算的操作。

成员函数说明
bitset <N> & operator &= (const bitset <N> & rhs);和另一个 bitset 对象进行与操作
bitset <N> & operator |= (const bitset <N> & rhs);和另一个 bitset 对象进行或操作
bitset <N> & operator ^= (const bitset <N> & rhs);和另一个 bitset 对象进行异或操作
bitset <N> & operator <<= (size_t num);左移 num 位
bitset <N> & operator >>= (size_t num);右移 num 位
bitset <N> & set();将所有位全部设成 1
bitset <N> & set(size_t pos, bool val = true);将第 pos 位设为 val
bitset <N> & reset();将所有位全部设成0
bitset <N> & reset (size_t pos);将第 pos 位设成 0
bitset <N> & flip();将所有位翻转(0变成1,1变成0)
bitset <N> & flip(size_t pos);翻转第 pos 位
reference operator[] (size_t pos);返回对第 pos 位的引用
bool operator[] (size_t pos) const;返回第 pos 位的值
reference at(size_t pos);返回对第 pos 位的引用
bool at (size_t pos) const;返回第 pos 位的值
unsigned long to_ulong() const;将对象中的0、1串转换成整数
string to_string () const;将对象中的0、1串转换成字符串(Visual Studio 支持,Dev C++ 不支持)
size_t count() const;计算 1 的个数
size_t size () const;返回总位数
bool operator == (const bitset <N> & rhs) const;如果两容器的位序列完全相等,则返回true;否则返回false.
bool operator != (const bitset <N> & rhs) const;如果两容器的位序列不完全相等,则返回true;否则返回false
bool test(size_t pos) const;测试第 pos 位是否为 1
bool any() const;判断是否有某位为1
bool none() const;判断是否全部为0
bitset <N> operator << (size_t pos) const;返回左移 pos 位后的结果
bitset <N> operator >> (size_t pos) const;返回右移 pos 位后的结果
bitset <N> operator ~ ();返回取反后的结果
bitset <N> operator & (const bitset <N> & rhs) const;返回和另一个 bitset 对象 rhs 进行与运算的结果
bitset <N> operator | (const bitset <N> & rhs) const;返回和另一个 bitset 对象 rhs 进行或运算的结果
bitset <N> operator ^ (const bitset <N> & rhs) const;返回和另一个 bitset 对象 rhs 进行异或运算的结果
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值