长久以来,软件界一直希望建立一种可重复利用的东西,以及一种得以制造出”可重复运用的东西”的方法,从函数(functions),类别(classes),函数库(function libraries),类别库(class libraries)、各种组件,从模块化设计,到面向对象(object oriented ),为的就是复用性的提升。
复用性必须建立在某种标准之上。但是在许多环境下,就连软件开发最基本的数据结构(data structures) 和算法(algorithm)都未能有一套标准。大量程序员被迫从事大量重复的工作,竟然是为了完成前人已经完成而自己手上并未拥有的程序代码,这不仅是人力资源的浪费,也是挫折与痛苦的来源。
为了建立数据结构和算法的一套标准,并且降低他们之间的耦合关系,以提升各自的独立性、弹性、交互操作性(相互合作性,interoperability),诞生了STL。
STL(Standard Template Library,标准模板库),是惠普实验室开发的一系列软件的统称。现在主要出现在 c++中,但是在引入 c++之前该技术已经存在很长时间了。
STL 从广义上分为: 容器(container) 算法(algorithm) 迭代器(iterator)。
容器和算法之间通过迭代器进行无缝连接。STL 几乎所有的代码都采用了模板类或者模板函数,这相比传统的由函数和类组成的库来说提供了更好的代码重用机会。
包含常用头文件
#include< iostream >
#include< cstdio >
#include< algorithm >
#include< cstring >
变长数组,倍增的思想(系统为程序或者进程分配空间时,所需时间与空间大小无关,而与申请次数有关),因此vector要尽量减少申请的次数,可以浪费空间,每次数组长度不够的时候,把数组的长度*2,之前的元素copy过来。假设数组长度是n,预计要copy数的次数平均情况下是O(1),申请次数是O(logn);
初始化一个vector
vector< int > a(10);
初始化一个vector并将所有位置的元素赋给一个初值
vector< int > a(10,3)
定义一个vector数组
vector< int > a[10];//定义了10个vector
//以下两个函数是所有容器都具有的,O(1)
a.szie()//返回元素个数;
a.empty();//a是不是空的,空 return true,非空,return false
a.clear();//清空
a.front();//返回第一个数,a.back()//返回最后一个数
a.push_back();//向vector的最后一个位置插入一个数,
a.pop_back();//向vector的最后的一个数删除
///迭代器
a.begin();//vector的第0个数,
a.end();// vector的最后一个数的后边一个数
//vector支持随机选取(同普通数组一样)
//支持比较操作(按照字典序)
pair可以看成是一个含两个元素的结构体,并且自带比较函数
存储一个二元组,定义的格式:
pair
a.first();//取得第一个元素
a.second();//取得第二个元素
支持比较运算,排序也是按照字典序比较(first为第一关键字,second为第二关键字)
构造一个pair: a=make_pair(10,“string”);或者a={10,“string”};
//可以嵌套使用来存储三个东西
pair
常用函数
substr(参数1,参数2)返回一个子串,参数1是字符串的起始位置,参数2是你要返回的子串的长度,
比如string a=“string”;
cout<
//添加一个字符串或者一个字符,
string a;
a+="string”;
a+=‘c’;
push();//向队尾插入一个元素
front();//返回一个队头的元素
back();//返回一个队尾的元素
pop();//弹出队头元素
size();
empty();
#include< queue >
优先队列,实现原理是使用堆实现的,定义的时候默认是大根堆,
//定义大根堆
priority_queue< int > heap;
//定义小根堆
#include< vector > //额外包含头文件
prioity_queue
push();//插入一个元素
top();//返回堆顶元素
pop();//弹出堆顶元素
栈,
push();//向栈顶插入一个元素
top();//返回栈顶元素
pop();//弹出栈顶元素
size();
empty();
双端队列
push_back();//在队尾插入元素
pop_back();//弹出队尾元素
push_front();//在队头插入元素
pop_front();//弹出队头元素
size();
empty();
clear();
[];//支持随机选取
缺点:效率较低
set的所有有关操作的时间复杂度都是logn;
set< int > s;//set中不允许有重复元素
multiset< int > ms;//multiset中允许有重复元素
set/multiset:
size();
empty();
insert();//插入一个元素
find();//查找一个数
count();//返回一个数的个数
erase();
(1)输入是一个数x,删除所有等于x的结点 O(logn+k)k是x的个数
(2)输入是一个迭代器,删除这个迭代器
lower_bound();//返回大于等于x的最小的数的迭代器,
upper_bound();//返回大于x的最小的数的迭代器,
//如果不存在的话,返回end();
两个元素做映射
insert();插入的数是一个pair
erase();输入的数是pair或者迭代器
find();
[];像数组一样
比如:
map< int string > a;
a[“string”]=1;//将string映射到1
cout< 也可以反过来用
//注:这种用法的时间复杂度是O(logn);
lower_bound(),upper_bound();
增删改查都是logn(上边的)
和上边对应的容器是一样的,唯一的区别是这是无序的,
没有lower_bound();upper_bound();也不支持迭代器的++,–;
优点:增删改查的时间复杂度都是O(1);
压位,节省8倍空间,bool类型的是一个字节(1bit),开一个1024的bool数组需要1024bit=1kb的内存
如果想要存储一个10000*10000的bool矩阵,需要10^8bit=100mb的空间,如果题目给定空间限制是64MB会爆内存,这时就用bitset便可以实现12mb的空间即可存储这10的8次方的矩阵
//定义bitset
bitset<个数> s;
//支持位运算操作
取反:~
与:&
或:|
异或:^
移位操作:>> <<
等于不等于:== !=
括号操作:[]取出某一位0,1
count();//返回有多少个1;
any();//返回是否至少有一个1
none();//判断是否全为0,全为0是true;
set();//将所有位制成1
set(k,v);//将第k位变成1
reset();//将所有位变成0,
flip();//把所有位取反,等价于~
flip(k);//把第k位取反