您的位置:首页 > 编程语言 > C语言/C++

C++STL简介

2018-01-24 11:37 274 查看
百度的说法:STL是Standard Template Library的简称,中文名标准模板库,STL可分为容器(containers)、迭代器(iterators)、空间配置器(allocator)、配接器(adapters)、算法(algorithms)、仿函数(functors)六个部分。我这篇文章主要将STL分为三类:容器、算法、迭代器

1、容器:

顺序容器:保存元素的序列

Vector 向量:分配在连续内存,动态增长的数组,快速访问任意元素(常量时间),能在末端快速插入或删除元素(摊还常量时间,即大部分插入操作都是在常量时间内完成),但元素中间插入或删除元素较慢(线性时间)。

List 双向链表:不一定为连续内存,支持动态增长,随机访问元素较慢(线性时间),找到元素后插入或删除较快(常量时间)

Forward_list(仅限C++11) 单向链表:内存需求比list小,只支持向前迭代

Deque 双端队列:类似vector,快速的元素访问(常量时间),两端快速插入删除(摊还常量时间),序列中间插入和删除较慢(线性时间)

Array :标准数组替代品,能知道自己的大小,不会自动转换为指针类型,不提供插入删除操作,大小固定,允许在堆栈上分配内存,元素的访问速度极快(常量时间)

关联容器:

排序或有序关联容器: 关联了键和值,并对元素排序

set 集合:每个元素都是唯一,集合中每个元素最多有一个实例,元素按照一定顺序保存,提供了对数时间的插入、删除和查找操作,即插入删除比vecto快,比list慢,查找比list快,比vector慢。 需要保证元素顺序,插入/删除和查找性能接近时,优先使用set

Multiset :允许重复元素

Map 映射:保存键值对,按照键值的顺序保存元素,例如书号是键值,书名是对象值,其他方面,set和map一致,需要关联键值则使用map,否则使用set;map可以作为关联数组使用

Multimap:允许重复键的map

无序关联容器/哈希表:

Unordered_set:

Unordered_map:

Unordered_multiset:

Unordered_multimap:

前两个定义于,后两个定义于 ,行为上与对应有序关联容器类似,只是不对元素进行排序,无序关联容器的插入、删除和查找操作以平均常量时间完成,最糟糕为线性时间,查找元素的速度比普通map和set快很多,元素数量特别大时尤其如此

容器适配器:构建在某种标准顺序容器(vector、list或deque)上的简单接口

Queue 队列:标准先入先出,一端插入(摊还常量时间)、另一端取出元素(常量时间)

Priority_queue:优先队列,元素按照优先级从队列中移除,插入和删除比queue快,可视为带有意外的队列

Stack 栈:标准先入后出,只有顶部对象是可见的,提供快速的插入删除(常量时间)

其他:

Bitset:可视为bool值序列,有固定大小,不支持迭代器

bitsetvarm (M)

其中varm为变量名。

N表示该类型在内存中占的位数,是二进制。

M表示变量varm的初始值。

bitset 有三种声明方式。在缺省定义中,我们只需简单地指明位向量的长度。例如:

bitset< 32 > bitvec;

声明了一个含有32 个位的bitset,对象位的顺序从0 到31。缺省情况下所有的位都被初始化为0 。

当bitset对象的一位或多个位被设置为1 时any()返回true

如果bitset 对象的所有位都被设置为0 ,则none()操作返回true

count()操作返回被设置为1的位的个数

用set()操作或者下标操作符来设置某个单独的位,

例如:用整值类型将第27 位设置为1, 我们这样写

quiz1 |= 1<<27;

而用bitset 来做我们可以写

quizl[ 27 ] = 1;



quiz1.set( 27 );

要使用bitset 类我们必须包含相关的头文件

include < bitset>

,测试某个单独的位是否为1 也有两种方式

test()操作。用位置做参数,返回true或false, bitvec.test( 0 )或bitvec[0];

将某个单独的位设置为0 ,我们可以用reset()或下标操作符

flip()操作翻转整个bitset 对象或一个独立的位

bitvec.flip( 0 ); // 翻转第一位

bitvec[0].flip(); // 也是翻转第一位

bitvec.flip(); // 翻转所有的位的值

String 从技术角度看也是容器,可视为字符向量

接着说算法:

2、算法

按是否修改容器中的内容和排序及相关操作,给标准库中的算法函数进行分类

非修改性序列操作(12个)

循环 for_each() 对序列中的每个元素执行某操作

查找 find() 在序列中找出某个值的第一次出现的位置

find_if() 在序列中找出符合某谓词的第一个元素

find_end() 在序列中找出一子序列的最后一次出现的位置

find_first_of() 在序列中找出第一次出现指定值集中之值的位置

adjacent_find() 在序列中找出相邻的一对值

计数 count() 在序列中统计某个值出现的次数

count_if() 在序列中统计与某谓词匹配的次数

比较 mismatch() 找出两个序列相异的第一个元素

equal() 两个序列中的对应元素都相同时为真

搜索 search() 在序列中找出一子序列的第一次出现的位置

search_n() 在序列中找出一值的连续n次出现的位置

修改性序列操作(27个)

复制 copy() 从序列的第一个元素起进行复制

copy_backward() 从序列的最后一个元素起进行复制

交换 swap() 交换两个元素

swap_ranges() 交换指定范围的元素

iter_swap() 交换由迭代器所指的两个元素

变换 transform() 将某操作应用于指定范围的每个元素

替换 replace() 用一个给定值替换一些值

replace_if() 替换满足谓词的一些元素

replace_copy() 复制序列时用一给定值替换元素

replace_copy_if() 复制序列时替换满足谓词的元素

填充 fill() 用一给定值取代所有元素

fill_n() 用一给定值取代前n个元素

生成 generate() 用一操作的结果取代所有元素

generate_n() 用一操作的结果取代前n个元素

删除 remove() “删除”具有给定值的元素,实际上是将元素放在序列末尾,真正删除需要erase()算法

remove_if() 删除满足谓词的元素

remove_copy() 复制序列时删除具有给定值的元素

remove_copy_if() 复制序列时删除满足谓词的元素

唯一 unique() “删除”相邻的重复元素,实际上是将元素放在序列末尾,真正删除需要erase()算法,函数返回值是去重之后的尾地址,如

int num[10]={1,1,2,2,2,3,4,5,5,5}; int ans=unique(num,num+10)-num,ans是去重后的数组长度5【去重后的尾地址-数值起始地址】

unique_copy() 复制序列时删除相邻的重复元素

反转 reverse() 反转元素的次序

reverse_copy() 复制序列时反转元素的次序

环移 rotate() 循环移动元素

rotate_copy() 复制序列时循环移动元素

随机 random_shuffle() 采用均匀分布来随机移动元素

划分 partition() 将满足某谓词的元素都放到前面

stable_partition() 将满足某谓词的元素都放到前面并维持原顺序

序列排序及相关操作(27个)

排序 sort() 以很好的平均效率排序

stable_sort() 排序,并维持相同元素的原有顺序

partial_sort() 将序列的前一部分排好序

partial_sort_copy() 复制的同时将序列的前一部分排好序

第n个元素 nth_element() 将第n各元素放到它的正确位置

二分检索 lower_bound() 找到大于等于某值的第一次出现

upper_bound() 找到大于某值的第一次出现

equal_range() 找到(在不破坏顺序的前提下)可插入给定值的最大范围

binary_search() 在有序序列中确定给定元素是否存在

归并 merge() 归并两个有序序列

inplace_merge() 归并两个接续的有序序列

有序结构上的集合操作 includes() 一序列为另一序列的子序列时为真

set_union() 构造两个集合的有序并集

set_intersection() 构造两个集合的有序交集

set_difference() 构造两个集合的有序差集

set_symmetric_difference() 构造两个集合的有序对称差集(并-交)

堆操作 push_heap() 向堆中加入元素

pop_heap() 从堆中弹出元素

make_heap() 从序列构造堆

sort_heap() 给堆排序

最大和最小 min() 两个值中较小的

max()
b8e3
两个值中较大的

min_element() 序列中的最小元素

max_element() 序列中的最大元素

词典比较 lexicographical_compare() 两个序列按字典序的第一个在前

排列生成器 next_permutation() 按字典序的下一个排列

prev_permutation() 按字典序的前一个排列

3、迭代器

迭代器:

STL通过迭代器模式提供了访问容器元素使用的泛型抽象,每个容器都提供了容器特定的迭代器,迭代器实际上是增强的智能指针,这些指针知道如何遍历容器中的元素,所有迭代器都遵循c++标准中定义的特定接口,附容易理解的代码:

代码原帖;https://www.cnblogs.com/shiyangxt/archive/2008/09/11/1289493.html 强烈推荐大家去看看!

#include <iostream>
#include <list>

using namespace std;
typedef list<int> INTLIST;

//从前向后显示list队列的全部元素
void put_list(INTLIST list, char *name)
{
INTLIST::iterator plist;

cout << "The contents of " << name << " : ";
for(plist = list.begin(); plist != list.end(); plist++)
cout << *plist << " ";
cout<<endl;
}

//测试list容器的功能
int main(){
//list1对象初始为空
INTLIST list1;
//list2对象最初有10个值为6的元素
INTLIST list2(10,6);
//list3对象最初有9个值为6的元素,用链表给链表赋值
INTLIST list3(list2.begin(),--list2.end());

//声明一个名为i的双向迭代器
INTLIST::iterator i;

//从前向后显示各list对象的元素
put_list(list1,"list1");
put_list(list2,"list2");
put_list(list3,"list3");

//从list1序列后面添加两个元素
list1.push_back(2);
list1.push_back(4);
cout<<"list1.push_back(2) and list1.push_back(4):"<<endl;
put_list(list1,"list1");

//从list1序列前面添加两个元素
list1.push_front(5);
list1.push_front(7);
cout<<"list1.push_front(5) and list1.push_front(7):"<<endl;
put_list(list1,"list1");

//在list1序列中间插入数据3个9
list1.insert(++list1.begin(),3,9);
cout<<"list1.insert(list1.begin(),3,9):"<<endl;
put_list(list1,"list1");

//测试引用类函数
cout<<"list1.front()="<<list1.front()<<endl;
cout<<"list1.back()="<<list1.back()<<endl;

//从list1序列的前后各移去一个元素
list1.pop_front();
list1.pop_back();
cout<<"list1.pop_front() and list1.pop_back():"<<endl;
put_list(list1,"list1");

//清除list1中的第2个元素
list1.erase(++list1.begin());
cout<<"list1.erase(++list1.begin()):"<<endl;
put_list(list1,"list1");

//对list2赋值并显示
list2.assign(8,1);
cout<<"list2.assign(8,1):"<<endl;
put_list(list2,"list2");

//显示序列的状态信息
cout<<"list1.max_size(): "<<list1.max_size()<<endl;
cout<<"list1.size(): "<<list1.size()<<endl;
cout<<"list1.empty(): "<<list1.empty()<<endl;

//list序列容器的运算
put_list(list1,"list1");
put_list(list3,"list3");
cout<<"list1>list3: "<<(list1>list3)<<endl;
cout<<"list1<list3: "<<(list1<list3)<<endl;

//对list1容器排序
list1.sort();
put_list(list1,"list1");

//结合处理
list1.splice(++list1.begin(), list3);
put_list(list1,"list1");
put_list(list3,"list3");
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: