目录
一、概述
STL的一个重要特点就是数据结构和算法的分离
STL中包含的是堆栈、队列和其他许多标准数据结构的实现和许多重要泛化算法的实现。
STL提供大量的模版类和函数,其中最常用的是迭代器、容器、算法。
为避免和其他头文件冲突以及确保移植性,在头文件书写时缺省.h后缀
二、容器
容器类库中有7种类型:
- 向量
- 列表
- 双端列表
- 集合
- 映射
- 栈
- 队列
其中,前三个是顺序容器,中间两个是关系式容器,后两个是容器适配。
数据结构 | 描述 | 头文件 |
---|---|---|
向量<vector> | 连续存储元素,就像数组,自带实用性函数方法 | <vector> |
列表<list> | 由节点组成的双向链表,每个节点包含一个元素 | <list> |
双端列表<deque> | 连续存储的指向不同元素的指针所组成的数组 | <deque> |
集合<set> | 由结点组成的红黑树,每个结点都包含着一个元素,结点之间以某种作用于元素对的谓词排序,没有两个不同的元素能够拥有相同的次序 | <set> |
映射<map> | 由{key,value}组成的集合,以某种作用于键对上的谓词排序 | <map> |
栈<stack> | 后进先出顺序 | <stack> |
队列<queue> | 先进先出顺序 | <queue> |
以下使用了using namespace std;
,如果没有使用需要添加std::
,如std::vector<int> v;
。为了编写方便,我以下都省略此操作。
1、vector
vector<int> v; //int型数组,是空的
vector<int> v(10); //int类型,定义大小为10
vector<int> v(10,'a'); //直接初始化10个a字符
vector<int> v(b); //将b赋给v,b也是vector
vector<int> v(b.begin(),b.begin()+4); //将向量b的前五个数赋给v
vector<int> v(a,a+4); //a是个容量大于等于5的数组
v.size(); //容器尺寸大小
v.empty(); //判断v是否为空,空反1,实反0
char *b = v.data(); //将v转变为char数组,适用于转换为字符数组
for(vector<char>::iterator it=v.begin();it<v.end();it++)
temp.push_back(*it);
cout << v[3] << endl; //直接通过中括号索引
v[3] = 'b'; //也可以用来赋值
cout << v.at(3) << endl; //这也一样可以用于读取,但是不能赋值
v.clear(); //清空v内数据,不会更改v的地址,也不会更改v的最大容量
v.assign(10, 'a'); //从第一个开始替换为10个a,其他位置不变;如果位数不够,添加位数
v.front(); //第一个字符
v.front() = 'a'; //也可用于赋值
v.back(); //一样
v.back() = 'a';
v.push_back('a'); //从最后面插入数
v.pop_back(); //删除最后一个数
v.capacity(); //获取v的最大容量(系统为它分配的大小)
//注意下面的位置不是输入的数字索引,而是position,如v.begin()、6v.end()、v.begin()+5
v.erase(pos); //删除pos位置的数据,传回下一个数据的位置。
v.erase(beg,end); //删除[beg,end)区间的数据,传回下一个数据的位置。
2、list
list是双向链表,在操作中没有[]
或者at()
函数可以观察,只能通过迭代器实现数据的遍历
list<int>::iterator opt;
for(opt = l.begin();opt != l.end(); opt++)
cout << *opt;
l.insert(l.begin(),9); //开头处插入一个9
l.insert(l.begin(),2 ,9); //开头处插入2个9
l.insert(l.begin(),list.begin(),list.begin()+5); //把list表中前6个数据插入到l的开头
l.erase(l.begin()); //删除开头1个数据
l.sort(); //内部排序
swap(l1,l2); //两个表互换
l1.swap(l2); //等价
l.merge(l1); //l1合并到l中,l1在l后,并且清空l1
l.merge(l1,greater<int>()); //l1合并到l中,l1在l前,并且清空l1
push_back() 和front()和back()等函数和vector里都一样,只是list里多了个push_front()
3、deque
构造函数和前面的统一
可从头尾双方面存取数据
成员函数略
4、set
insert(); //插入数据
begin(); //返回set容器的第一个元素
end(); //返回set容器的最后一个元素
clear(); //删除set容器中的所有的元素
empty(); //判断set容器是否为空
max_size(); //返回set容器可能包含的元素最大个数
size(); //返回当前set容器中的元素个数
rbegin(); //返回的值和end()相同
rend(); //返回的值和rbegin()相同
count(); //用来查找set中某个某个键值出现的次数
erase(iterator); //删除定位器iterator指向的值
erase(first,second); //删除定位器first和second之间的值
erase(key_value); //删除键值key_value的值
find(); //寻找值
lower_bound(key_value); //返回第一个大于等于key_value的定位器
upper_bound(key_value); //返回最后一个大于等于key_value的定位器
5、map
map与前面的不一样,它是一个一对一的容器,即key——value,根据key值,可快速访问value。
由于格式不同,所以一些操作方法也不同。
// 第一种 用insert函數插入pair
m.insert(pair<int, string>(1, "a"));
// 第二种将同种map类型数据插入
m.insert(map<int, string>::value_type(2, "b"));
// 第三种 用数组方式插入
m[3] = "c";
//输出直接套用数组模版
cout << m[2] << endl;
6、stack
栈的功能不解释,它主要是三个函数构成功能
stack<char> s; //定义一个char类型栈
s.push('h'); //进栈一个元素
cout << s.top() << endl; //输出栈顶元素
s.pop(); //删除栈顶元素
s.empty(); //是否为空
s.size(); //栈内元素个数
7、queue
队列和栈的用法大致相当
q.push('c'); //进队
cout << q.front() << endl; //输出队前元素
q.pop(); //删除队前元素
q.empty(); //是否为空
q.size(); //队列元素个数
三、迭代器(*/iterator)
STL有5种迭代器:
- 正向迭代器(forward iterator)
- 双向迭代器(bidirectional iterator)
- 随机访问迭代器(random access iterator)
- 输入迭代器(input iterator)
- 输出迭代器(output iterator)
使用方法:
1、*——指针类型
如代码:
#include <iostream>
#include <algorithm>
using namespace std;
int a[10];
int main(int argc, const char * argv[]) {
a[6]=500;
int *ite = find(a, a+sizeof(a)/sizeof(int), 500);
if(ite == a+sizeof(a)/sizeof(int)) //ite到尾端
cout << "not found";
else
cout << *ite << " was found";
cout << endl;
return 0;
}
使用的常用的指针类型,定义一个int类型指针,使用find函数,将数组中找到的地址赋给指针,所以直接拜访指针即可.
并且迭代器指针是可以直接修改数组内部值的!
2、容器中的迭代器(iterator)
如代码:
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main(int argc, const char * argv[]) {
vector<int> v(10,5);
v[5] = 50;
vector<int>::iterator ite;
ite = find(v.begin(), v.end(), 50);
if(ite == v.end())
cout << "not found";
else
cout << "found";
cout << endl;
return 0;
}
注意,end成员函数返回的是v的最后一个元素后一个位置,也就是说直接访问end是一个位置数字,但是访问end-1即是v中最后一元素。
3、常量迭代器
在前文介绍的迭代器iterator是可进行直接赋值的,那么对v或数组来说就不安全。所以引入了常量迭代器const_iterator
。它的用法和iterator一样,只是,它是只读迭代器。
vector<int>::const_iterator con_ite;
四、string类型
string是最主要也是最重要的一种容器,单独列开单独讨论!
同样的,using namespace std;
赋值
string s;
string s("hello");
cin >> s;
大小
s.size();
s.length(); //都是计算大小
s.empty(); //查看是否为空
s.capacity(); //重新分配内存前的最大存储个数
检索
s[3] = 's';
s.at(3) = 's'; //等价
比较 =0时相等,>0时表示大于,<0时表示小于
string s("abcd");
s.compare("abcd"); //0
s.compare("dcba"); //<0
s.compare("ab"); //>0
s.compare(s); //=0
s.compare(0,2,s,2,2); //<0 ab?cd
s.compare(1,2,"bcx",2); //<0 bc?bc
修改内容
s.assign(str); //str赋给s
s.assign(str,1,3); //把str的1索引位置后的3个字符赋给s
s.assign(str,2,string::nopos); //把str的2-end赋给s
s.assign("IBM"); //字符串赋给s
s.assign("sony",5); //把sony以及\0赋给s
s.assign(5,'x'); //5个x赋给s
删除
s="";
s.clear();
s.erase(); //全删
s.erase(1,2); //删除1索引后的两个字符
s.erase(1); //删除1索引后的所有字符
尾端添加
s+=str; //把str加到s后
s+="hello"; //把“hello”加到s后
s+='a'; //把‘a’加到s后
s.append(str); //同s+=str
s.append(str,1,3); //将str的1-3索引字符加到s中
s.append(str,2,string::npos); //将str的2-end索引字符加到s中
s.append("hello"); //同s+="hello";
s.append("hello",3); //把“hello”的前三个字符加到s后
s.append(5,'x'); //把5个‘x’加到s后
s.push_back('a'); //s后加入一个字符‘a’
插入
s.insert(1,"hello"); //在1位置插入“hello”
s.insert(2,str); //在2位置插入str
替换
s.replace(3,2,"hello"); //替换3索引后的2个字符为“hello”
提取子串
s.substr(); //提取s的全部内容
s.substr(11); //提取索引11往后的字符子串
s.substr(5,6); //提取5索引后的6个字符子串
查找
string s("hello world!\nGood Morning!");
s.find("world"); //返回s中str的索引,如果不存在,返回一个超大值;返回6
s.find_first_of("world!") //返回“world!”中任意字符出现的最早位置;返回2
s.find_last_of("world"); //与上一条相反;返回25
s.find_first_not_of("help!") //返回“help!”中没有出现的第一个字符位置;返回4
s.find_last_not_of("help!") //与上一条相反;返回24
记住这些关键字:
find、substr、append、push_back、assign、compare
。
五、算法
在使用算法时,头文件为#include <algorithm>
提供给我们的函数接口太多了,仅写一些常用的。
成员函数:
1. find()
模版:template <class _InputIterator, class _Tp>
_InputIterator
find(_InputIterator __first, _InputIterator __last, const _Tp& __value_);
2. min()、max()
模版:template <class _Tp>
const _Tp&
min(const _Tp& __a, const _Tp& __b)
const _Tp&
max(const _Tp& __a, const _Tp& __b)
3.sort()
模版:template <class _Tp>
void
sort(_Tp** __first, _Tp** __last)
4.merge()
模版:template <class _InputIterator1, class _InputIterator2, class _OutputIterator>
_OutputIterator
merge(_InputIterator1 __first1, _InputIterator1 __last1,
_InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result)
5.binary_search()
模版:template <class _ForwardIterator, class _Tp, class _Compare>
bool
binary_search(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value_, _Compare __comp)
。。。。。。
4个排序算法:sort(),partial_sort(),partial_sort_copy(),stable_sort()
4个二分查找算法:binary_search(),lower_bound(),uper_bound(),equal_range()
2个用于合并有序区间的通用算法:
merge(),inplace_merge()
4个最值算法:
min(),max(),min_element(),max_element()
3个与排列方式有关的算法:lexicographical_compare(),next_permutation(),prev_permutation()
5个用于有序序列上的集合操作算法:includes(),set_union(),set_intersection(),set_difference(),set_symmetric_difference()
4个为堆创建和操作的算法:make_heap(),pop_heap(),push_heap(),sort_heap()