C++的STL及常用的容器

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/MOU_IT/article/details/87994575

1、STL简介   

    STL提供六大组件,彼此可以组合套用:
  (1)容器:容器用来存放数据,从实现的角度看,STL容器是一种类模板,包括vector、list、deque、set、map等。
  (2)算法:STL算法是一种函数模板,各种常用的算法如sort、search、copy、erase等。
  (3)迭代器:扮演容器与算法之间的胶合剂,是所谓的“泛型指针”,共有五种类型,以及其它衍生变化。从实现的角度看,迭代器是一种将operator*、operator->、operator++、operator--等指针相关操作予以重载的类模板,所有STL容器都附带有自己专属的迭代器。
  (4)仿函数:行为类似函数,可以作为算法的某种策略。从实现的角度看,仿函数是一种重载了operator()的类或者类模板。
  (5)适配器:一种用来修饰容器或仿函数或迭代器接口的东西。例如stack和queue,虽然看似容器,但是只能算一种容器适配器,因为它们的底层完全借助deque,所有的操作都由底层的deque供应。
  (6)分配器:负责空间配置和管理,从实现的角度讲,配置器是一个实现了动态空间配置、空间管理、空间释放的类模板。通常,分配器是由两级分配器构成的内存管理器,当申请的内存大于128B时,就启用第一级分配器通过malloc直接向系统的堆空间分配,如果申请的内存小于128B时,就启用第二级分配器,从一个预先定义好的内存池取一块内存交付给用户,这个内存池由16个不同大小(8~128B)空闲列表组成,分配器会根据申请内存的大小(将这个大小round up成8的倍数)从对应的空闲列表取表头块给用户。这种做法有两个优点:1)小对象快速分配,小对象从内存池分配;2)小对象从内存池分配,避免了内部碎片的产生。    

    六大组件关系:容器(containers)通过分配器(allocators)取得数据储存空间,算法(algorithms)通过迭代器(iterators)存取容器的内容,仿函数(functors)可以协助算法完成不同的策略变化,适配器(adapters)可以修饰或套接仿函数。

2、STL中的容器及底层实现:

  (1)动态数组vector:底层数据结构为数组 ,支持快速随机访问;

  (2)静态数组array:底层数据结构为数组 ,支持快速随机访问;

  (3)双端队列deque:底层数据结构为一个中央控制器和多个缓冲区,支持首尾(中间不能)快速增删,也支持随机访问。deque是一个双端队列(double-ended queue),也是在堆中保存内容的.它的保存形式如下:[堆1] --> [堆2] -->[堆3] --> ...每个堆保存好几个元素,然后堆和堆之间有指针指向,看起来像是list和vector的结合品。

  (4)双向链表list:底层数据结构为双向链表,支持快速增删;

  (5)单向链表forward_list:

  (6)有序集合set:底层数据结构为红黑树,有序,不重复

  (7)有序元素可重复集合multiset:底层数据结构为红黑树,有序,可重复 

  (8)有序字典map:底层数据结构为红黑树,有序,不重复

  (9)有序元素可重复字典multimap:底层数据结构为红黑树,有序,可重复

扫描二维码关注公众号,回复: 5555210 查看本文章

  (10)无序集合unordered_set:

  (11)无序元素可重复集合unordered_multiset:

  (12)无序字典unordered_map:

  (13)无序元素可重复字典unordered_multimap:

  (14)字符串string:

  (15)栈stack:底层一般用list或deque实现,封闭头部即可,不用vector的原因应该是容量大小有限制,扩容耗时;

  (16)队列queue:底层一般用list或deque实现,封闭头部即可,不用vector的原因应该是容量大小有限制,扩容耗时;

  (17)优先级队列priority_queue:

  (18)bit集合bitset:

3、常用的几个容器vector、set、map、stack、queue、string及其成员函数

(1)容器的公用函数:

vector<int> v1 = {x1,x2,...} 第一种初始化方式
vector<int> v2{x1,x2,...} 第二种初始化方式

list<int> l;

vecto<int> v3(l.begin(), l.end())

第三种初始化方式,以另种容器的元素为初值

int carray[] = {x1,x2,...}

set<int> c(begin(carray), end(carray))

第四种初始化方式,以某个C语言的array的元素作为初值
for(const auto& elem : coll){ elem } 只读的方式访问元素,auto自定确定容器的元素类型
for(auto& elem : coll){ elem } 可写的方式访问元素
for(auto pos = coll.cbegin(); pos!=coll.cend(); ++pos){  *pos  } 迭代器的方式只读访问元素
for(auto pos = coll.begin(); pos!=coll.end(); ++pos){ *pos } 迭代器的方式可写访问元素
c.empty() 判断容器是否为空,为空则返回true,否则返回false
c.size() 返回容器的元素数量,不适合forward_list<>
c.begin() 返回一个iterator,指向第一个元素
c.end() 返回一个iterator,指向最末元素的下一个位置
c.cbegin() 返回一个const iterator,指向第一个元素
c.cend() 返回一个const iterator,指向最末元素的下一个位置
c.clear() 移除所有元素,令容器为空,不适用于array<>

(2)动态数组vector<>

    vector将其元素放在一个动态数组中管理,它允许随机访问,在vector尾部附加或者移除元素都很快,但是在vector中间或起始段安插元素比较费时。

vector<int> v1

vector<int> v2 = v1

vector<int> v2(v1)

vector<int> v2(n)

vector<int> v2(n, elem)

vector<int> v2(beg, end)

vector<int> v2(initlist)

vector<int> v2 = initlist.

产生一个空的vector

使用v1初始化v2

使用v1初始化v2

构建一个大小为n的vector

构建一个大小为n的vector,每个元素为elem

使用iterator初始化v2

使用初始化列表初始化v2

使用初始化列表初始化v2

v.~vector() 销毁所有元素,释放内存
v.capacity() 返回不进行空间重新分配条件下的元素最大容纳量
v.reserve(num) 如果容量不足,扩大容量
v.shrink_to_fit() 降低容量以符合元素个数
v.assign(n, elem) 复制n个elem,复制给v
v.assign(beg, end) 将区间内元素赋值给v
v.assign(initlist) 将初值列赋值给v
v1.swap(v2) 交换v1和v2的数据
swap(v1, v2) 交换v1和v2的数据
v [idx] 返回索引idx所指的元素
v.at( idx ) 返回索引idx所指的元素
v.front() 返回第一个元素
v.back() 返回最后一个元素
v.rbegin() 返回反向iterator指向的反向迭代的第一个元素
v.rend() 返回反向iterator指向的反向迭代最后一个元素的下一个位置
v.crbegin() 返回const iterator反向迭代的第一个元素
v.crend() 返回const iterator反向迭代的最后一个元素的下一个位置
v.push_back(elem) 附加一个elem到末尾
v.pop_back() 移除最后一个元素,但是不返回它
v.insert(pos, elem) 在iterator位置pos之前插入elem,并返回新元素位置
v.insert(pos, n, elem) 在iterator位置pos之前插入n个elem,并返回第一个新元素位置
v.insert(pos, beg, end) 在iterator位置pos之前插入区间内所有元素,并返回第一个新元素位置
v.insert(pos, initlist) 在iterator位置pos之前插入initlist所有元素,并返回第一个新元素位置
v.emplace(pos, args...) 在iterator位置pos之前插入一个以args为初值的元素,并返回新元素位置
v.emplace_back(args...) 附加一个以args为初值的元素于末尾,不返回任何东西
v.erase(pos) 移除iterator位置pos上的元素,返回下一个元素位置
v.erase(beg, end) 移除区间内的所有元素,返回下一个元素位置
v.resize(num) 将元素量改为num,多出的元素用default构造函数完成初始化
v.resize(num, elem) 将元素量改为num,多出的元素用elem初始化

strcpy(&v[0], "hello world")

strcpy(v.data(), "hello world")

printf("%s\n", v.data())

把vector当做C语言中的数组使用

(3)有序集合set<>

    set通常是由平衡二叉树实现出来(通常用红黑树实现),在二叉树中,每个节点都有一个父节点和两个子节点,左子树的所有元素都比自己小,右子树的所有元素都比自己大。set的主要优点是,它能很快找出一个具有某特定value的元素,因为它具备对数的复杂度,而对于循序式容器的复杂度是线性的。然而它的一个缺点是,你不能直接改变元素的value,因为那会破坏元素的自动排序。

set<int> s1

set<int> s1(op)

set<int> s2 = s1

set<int> s2(s1)

set<int> s2(beg, end)

set<int> s2(beg, end, op)

set<int> s2(initlist)

set<int> s2 = initlist

s2.~set()

set<int>

set<int, op> 

默认构造函数,建立一个空的set

建立一个空的set,以op作为排序规则

Copy构造函数,为相同类型的另一个set建立一份拷贝,所有元素均被复制

Copy构造函数,为相同类型的另一个set建立一份拷贝,所有元素均被复制

以区间内的元素作为初值,建立一个set

以区间内的元素为初值,以op为排序准则,建立一个set

以初值initlist的元素为初值建立一个set

以初值initlist的元素为初值建立一个set 

销毁所有的元素,释放内存

一个set,以less<>(operator <)为排序准则

一个set,以op为排序准则

s.key_comp() 返回“比较准则”
s.value_comp() 返回针对value的“比较准则”,和key_comp()相同
s.count(val) 返回元素值为val 的元素个数
s.find(val) 返回元素值为val 的第一个元素,如果找不到就返回end()
s.lower_bound(val) 返回val的第一个可安插位置,就是元素值>=val的第一个元素位置
s.upper_bound(val) 返回val的最后一个可安插位置,就是元素值>val的第一个元素位置
s.equal_range(val) 返回val可被安插的第一个位置和最后一个位置,就是元素值==val的元素区间
s1.swap(s2) 交换s1和s2的数据
swap(s1, s2) 交换s1和s2的数据
s.rbegin() 返回反向iterator指向的反向迭代的第一个元素
s.rend() 返回反向iterator指向的反向迭代最后一个元素的下一个位置
s.crbegin() 返回const iterator反向迭代的第一个元素
s.crend() 返回const iterator反向迭代的最后一个元素的下一个位置
s.insert(val) 安插一个val拷贝,并返回新元素位置
s.insert(pos, val) 安插val的拷贝,返回新元素位置,pos是个提示,指出安插动作的查找起点
s.insert(beg, end) 将区间内所有元素拷贝到s,无返回值
s.insert(initlist) 插入initlist所有元素,无返回值
s.emplace(args...) 插入一个以args为初值的元素,并返回新元素位置
s.emplace_hind(pos, args...) 插入一个以args为初值的元素,并返回新元素位置,pos是个提示,指出安插动作的查找起点
s.erase(val) 移除与val相等的所有元素,返回被移除的元素个数
s.erase(pos) 移除iterator位置pos上的元素,无返回值
s.erase(beg, end) 移除区间内的所有元素,无返回值

(4)有序字典map<>

    map和set类似,通常由平衡二叉树完成,可以把set看作特殊的map,只不过set的key和value是同一对象。因此,map拥有set的所有能力和所有操作。唯一的区别是map的元素key/value的键值对,此外map可以作为关联式数组来运用。map会根据key自动对元素排序,这一性质使得map身上有一条重要限制:你不可以直接改变元素key,因为这会破坏正确次序,要修改元素的key,必须先移除拥有该key的元素,然后插入拥有新key/value的元素。

map<int> m1

map<int> m1(op)

map<int> m2 = m1

map<int> m2(m1)

map<int> m2(beg, end)

map<int> m2(beg, end, op)

map<int> m2(initlist)

map<int> m2 = initlist

m2.~map()

map<key, val>

map<key, val, op> 

默认构造函数,建立一个空的map

建立一个空的map,以op作为排序规则

Copy构造函数,为相同类型的另一个map建立一份拷贝,所有元素均被复制

Copy构造函数,为相同类型的另一个map建立一份拷贝,所有元素均被复制

以区间内的元素作为初值,建立一个map

以区间内的元素为初值,以op为排序准则,建立一个map

以初值initlist的元素为初值建立一个map

以初值initlist的元素为初值建立一个map

销毁所有的元素,释放内存

一个map,以less<>(operator <)为排序准则

一个map,以op为排序准则

m[key] 如果关键字为key的元素不存在,则安插关键字为key的元素,如果不设置value,value默认初始化为0。如果存在则返回value值。
m.at(key) 返回key对应的value,如果该元素不存在则抛出异常

for(auto iter = m.begin();iter!=m.end();iter++){

    cout<<iter->first<<endl;

    cout<<iter->second<<endl;

}

遍历map中的所有元素
m.key_comp() 返回“比较准则”
m.value_comp() 返回针对value的“比较准则”,和key_comp()相同
m.count(val) 返回key为val 的元素个数
m.find(val) 返回key为val 的第一个元素,如果找不到就返回end()
m.lower_bound(val) 返回key=val的第一个可安插位置,就是key>=val的第一个元素位置
m.upper_bound(val) 返回key=val的最后一个可安插位置,就是key>val的第一个元素位置
m.equal_range(val) 返回key=val可被安插的第一个位置和最后一个位置,就是key==val的元素区间
m1.swap(m2) 交换m1和m2的数据
swap(m1, m2) 交换m1和m2的数据
m.rbegin() 返回反向iterator指向的反向迭代的第一个元素
m.rend() 返回反向iterator指向的反向迭代最后一个元素的下一个位置
m.crbegin() 返回const iterator反向迭代的第一个元素
m.crend() 返回const iterator反向迭代的最后一个元素的下一个位置
m.insert(val) 安插一个val拷贝,并返回新元素位置
m.insert(pos, val) 安插val的拷贝,返回新元素位置,pos是个提示,指出安插动作的查找起点
m.insert(beg, end) 将区间内所有元素拷贝到s,无返回值
m.insert(initlist) 插入initlist所有元素,无返回值
m.emplace(args...) 插入一个以args为初值的元素,并返回新元素位置
m.emplace_hind(pos, args...) 插入一个以args为初值的元素,并返回新元素位置,pos是个提示,指出安插动作的查找起点
m.erase(val) 移除与val相等的所有元素,返回被移除的元素个数
m.erase(pos) 移除iterator位置pos上的元素,无返回值
m.erase(beg, end) 移除区间内的所有元素,无返回值

(5)字符串string

=、assign() 赋予新值
swap() 交换两个string的内容
+=、append()、push_back()

添加字符。

str1.append(str2,1,3)表示将str2的从索引1开始的三个字符附加到str1;

str1.append("nico",5)表示将添加字符串数组:'n'  'i'  'c'  'o'  '\0';

str1.append(5, 'x') 表示添加5个x;

insert(index,str)

插入字符

erase()、pop_back()

删除字符

str.erase(13):删除第13个字符

str.erase(7, 5):删除第七个位置后的5个字符

clear() 移除全部字符使之为空
resize() 改变字符数量
replace(index,num,str2) 替换字符,将str中重index开始的num个字符替换为str2
+ 串接string
==,!=,<=,>=,compare()

比较string,str1.compare(str2)中,返回0表示相等、小于0表示小于,大于0表示大于;

str1.compare(0, 2,str2,2, 2)表示比较str1的从0开始的2个字符和str2的从2开始的两个字符;

str1.compare(1,2,“bcx”,2)表示比较str1的从1开始的两个字符和“bcx”中的“bc”;

empty() 判断字符是否为空
size()、length() 返回字符的数量
max_size() 返回字符的最大可能数

capacity()

返回重分配前的字符容量
reserve() 保留一定容量内存以容纳一定数量的字符
shringk_to_fit() 缩减字符使符合当前字符量
[]、at 访问某个单一字符
front()、back() 访问第一个、最末字符
>>,getline() 从一个stream读取某值
<< 将某值写入stream
stoi()、stol()、stoll()

将string转为带正负号的整数(int、long、long long),转换时会跳过前导的任何空白字符

    stoi(str,idxRet,base=10):第二个参数用于保存字符中未被处理的第一个字符索引,也就是字符串中的第一个无效字符,如果不关心则设置nullptr,第三个参数是数值的基数。

stoul()、stoull() 将string转为不带正负号的整数(unsigned int、unsigned long long)
stof()、stod()、stold() 将string转为浮点数(float、double、long double)
to_string(val)、to_wstring(val) 将整数、浮点数转为string
const char c = 'a';
string s(1,c);        ---------------------
string s1;             ---------------------
s1.push_back(c); 
stringstream ss;  ---------------------
ss << c;
string str2 = ss.str();

将char转为string的三种方法:

  1.使用 string 的构造函数;

  2.声明string 后将char push_back;

  3.使用stringstream;

copy(buffer,num,beg_index) 将string复制为一个字符数组
data()、c_str() 将string的内容以C-string的内容返回
substr()

返回某个子字符串:

    str.substr(11):返回str的11个位置后的所有子串

    str.substr(5, 6) :返回str的第5个位置后的6个字符

find()

rfind()

find_first_of()

find_last_of()

find_first_not_of()

find_last_not_of()

查找第一个与val相等的字符串,返回索引;

    str1.find(str2,10):表示从str1的第10个位置开始查找

查找最后一个与val相等的字符串,返回索引;

查找第一个与val中的某值相等的字符串;

查找最后一个与val中的某值相等的字符串;

查找第一个与val中的任何值都不相等的字符串;

查找最后一个与val中的任何值都不相等的字符串;

begin()、end() 提供正常的iterator支持
cbegin()、cend() 提供const iterator支持
rbegin()、rend() 提供reverse iterator支持
crbegin()、crend() 提供const reverse iterator支持
get_allocator() 返回分配器

(6)栈stack<>

stack<string> stack 初始化一个空的栈
stack.push(val) 将一个元素放入stack之内
stack.top() 返回stack的下一个元素,但并不移除它
stack.pop() 从stack中移除元素,但并不返回它

(7)队列queue<>

queue<string> queue 初始化一个空队列
queue.push(val) 将一个元素放入队列内
queue.front() 返回队列的下一个元素(也就是第一个被插入的元素),但不移除它
queue.back() 返回队列的最后一个元素(也就是最后一个被插入的元素),但不移除它
queue.pop() 从队列中移除下一个元素,但并不返回它

猜你喜欢

转载自blog.csdn.net/MOU_IT/article/details/87994575