面经笔记本 语言基础理论 【五:C++ STL】

目录

零、模板

一、STL基本概念

二、string

三、vector

四、list

五、vector与list

六、deque

七、set\multiset

八、map\multimap\unordered_map

8.1 map与unordered_map

九、仿函数

十、谓词


零、模板

1.C++提供两种模板

函数模板和类模板

语法:

template

template

函数模板:

typename表示这个后面的符号是一种数据类型,

T表示一种通用的数据类型,名称可以替换,通常为大写字母

使用函数模板有两种方式:

自动类型推导,显示指定类型。

一般我们采用显示指定类型的方式,也就是在函数名后,括号前加上

类模板:

建立一个通用类,类中成员的数据类型可以不具体指定,用一个虚拟的类来代表。

2.模板的问题

如果T的数据类型是自定义类型,那么可以重载模板,提供具体化的模板。

3.类模板与函数模板的区别

1. 类模板没有自动类型推导的使用方式,必须声明类型

2. 类模板在模板参数列表中可以有默认参数

4.类模板中成员函数创建时机

普通类中的成员函数一开始就可以创建

类模板中的成员函数在调用时才创建

一、STL基本概念

为了简化数据结构与算法的题韬标准,运用了面向对象和泛型编程思想,调高复用性,诞生了STL,标准模板库。

STL广义上由以下三部分组成:

1.容器

2.算法

3.迭代器

STL几乎所有的代码都采用模板类或模板函数

容器:

序列式容器:强调值的排序,每个元素均有固定的位置。

关联式容器:二叉树或哈希表结构,各个元素之间没有严格的物理顺序关系。

算法:

质变算法:改变区间内元素的内容,如拷贝,替换,删除

非质变算法:运算过程中不会更改区间内元素内容,如查找,遍历。

迭代器:

提供一种方法,使之能依序寻访某个容器中的各个元素,非常类似于指针。

二、string

string是C++风格的字符串,本质是一个类

他和char*的区别在于,

char*是一个字符类型的指针,

但是string是一个类,类的内部封装了char*。

string类管理char*所分配的内存,不用担心复制越界和取值越界,由类的内部进行负责。

三、vector

vector的数据结构和数组非常相似,也称为单端数组。

他和数组的区别在于,数组是静态空间,而vector可以动态扩展。

vector的动态扩展并不是在原空间之后续接新空间,而是找更大的内存空间,然后将原数据拷贝到新空间,再释放原空间。

通过capacity():返回容器的容量

通过size():返回容器中元素的个数

通过resize():重新指定容器的长度为num

vector收缩内存:

利用匿名对象加swap:

举个例子

用一个vector v,

里面存放了1到100000的数

但是其实喜用帮助我们扩容了,总容量差不多有130000左右

这怎么办?

我们可以先用v.resize(100000),

调整v的元素长度为100000,这个时候什么都没有改变。

然后,我们使用拷贝构造函数,创建一个匿名对象:

vector(v).swap(v)

这个匿名对象会根据v的当前元素个数来确定自己的元素个数和容量,

也就是说,这个时候,匿名对象的容量和元素个数都是100000.

在调用他的交换函数,

将自己与原容器v进行交换,

这个时候,v就删去了之前多的容量,

而这个匿名对象指向的空间,

也会因为匿名对象的一个特点被系统回收。

这个特点是:匿名对象运行完本行,立即被销毁。

vector优点:

1.不需要指定内存大小就可以像数组一样操作,而且可以进行动态操作,如:push_back(),pop_back(),insert()等。

2.随机访问方便,可以随机访问vector内的任意一个元素。

3.节省空间

缺点:

1.插入和删除操作效率低,尤其是头部。

2.操作仅能在尾部进行push和pop

3.当动态添加的数据超过vector默认分配的大小时,要进行整体的重新分配、拷贝和释放。

四、list

功能:链式存储

底层:一个双向循环链表

每一个数据都有数据域,指向前一个元素的指针和指向后一个元素的指针。

优点:

1.动态存储分配,不会造成内存浪费

2.插入和删除效率高

缺点:

1.指针域占用了一定的空间

2.遍历元素,查找元素开销较大

五、vector与list

1.如果需要高效的随机存取,不在乎插入和删除的效率,使用vector

2.如果需要大量的插入和删除元素,使用list

3.list里,进行插入和删除操作都不会造成原有的list迭代器失效,这在vector里是不成立的。

六、deque

deque又叫做双端数组,它可以在头端和尾端进行插入删除操作。

deque相对于vector,对头部的插入和删除速度比vector快。

vector访问元素时的速度会比deque快。

七、set\multiset

set和multiset属于关联式容器,

底层实现:红黑树

map中的元素:对组

对组

成对出现的数据,利用队组可以返回两个数据。

pair p1 (string(“Tom”),20);

pair p2 = make_pair(“Jerry”,10);

特性:

1.set中每个元素必须是唯一的,不允许出现键值重复。可以理解为一个集合。

2.内部所有的元素都会被自动按照升序来排序。

可以改降序:使用仿函数,重写()括号运算符,

使用二元谓词,

bool operator()(int v1,int v2)

{

return v1>v2;

}

3.如果set中的元素为对组形式,可以根据key值快速找到value的值

.first,

.second

即可

4.multiset

multiset和set的区别在于multiset的元素可以相同,也就是内部可以出现重复的键值。

对multiset进行erase操作后,会删除所有值相同的key。

八、map\multimap\unordered_map

map提供键和值一对一的映射关系,

map中的所有元素都是对组。

其中第一个元素为key,键值,起到索引作用;

第二个元素为value,也就是实值。

每个键不允许重复,不允许修改。

但是map对应的值是可以修改的。

所有元素会根据元素的键值自动排序。

底层结构:红黑树

multimap允许容器中有重复的key值。

也就是说,一个键可以对应多个值,键和值一对多的映射关系。

8.1 map与unordered_map

unordered_map

内部是一个哈希表,也叫散列表,通过把关键key值映射到哈希表中的某一个位置来访问记录,时间复杂度可达O(1)。

其元素的排列顺序是无序的。

map

内部是一个红黑树,

红黑树不同于二叉平衡搜索树,他是非严格的二叉平衡搜索树,具有自动排序的功能。

红黑树的每个结点都代表map中的一个元素。

map优点:有序,且map底层为红黑树,使得很多操作在o(logn)的时间复杂度下就可以实现。

缺点:空间占用率高,因为红黑树的每一个结点都需要额外保存父节点,孩子节点以及红黑树本身的性质,使得空间占用率大。

unordered_map:

优点:因为内部实现了哈希表,所以查找速度非常快,性能优于基于红黑树的map;

缺点:哈希表建立比红黑树建立更费时。

所以对于查找问题,我们使用unordered_map会高效一些;

而如果我们想得到一个有序序列,那么使用map。

九、仿函数

仿函数又叫做函数对象,

重载函数操作符的类,他的对象通常叫做函数对象。

因为函数对象使用重载的()运算符时,行为类似函数调用,

所以也称仿函数。

可以有参数,可以有返回值

class MyAdd

{

public :

       int operator()(int v1,int v2)

       {

              return v1 + v2;

       }

};

 

MyAdd myAdd;

       cout << myAdd(10, 10) << endl;

十、谓词

返回bool类型的仿函数称为谓词;

如果重载的括号运算符接受一个参数,那么叫一元谓词;

如果重载的括号运算符接受两个参数,那么叫二元谓词。

你可能感兴趣的:(C++)