STL
1.STL概论
1.1STL六大组件
容器、算法、迭代器、仿函数、适配器、空间配置器
1.2STL优点
内建在C++编译器中,不需要安装额外内容
不需要了解具体实现内容,只要熟练运用即可
高复用,可移植,高性能
1.3容器划分
序列式容器
关联式容器 有个key起到索引作用
1.4算法
质变算法,改变元素的内容或者位置。
非质变算法,对原数组无变化。
2.容器
2.1vector
以数组为核心机制的动态集合对象,
创建一个vector容器
vector<int>v; //创建一个vector容器,容器中存放元素类型是int类型
vector(v.begin(), v.end());//将v[begin(), end())区间中的元素拷贝给本身。
vector(n, elem);//构造函数将n个elem拷贝给本身。
vector(const vector &vec);//拷贝构造函数。
插入和删除元素
insert(const_iterator pos, int count,ele);//迭代器指向位置pos插入count个元素ele.
push_back(ele); //尾部插入元素ele
pop_back();//删除最后一个元素
erase(const_iterator start, const_iterator end);//删除迭代器从start到end之间的元素
erase(const_iterator pos);//删除迭代器指向的元素
clear();//删除容器中所有元素
//插入元素
v.push_back(10);
v.push_back(30);
v.push_back(20);
v.push_back(40);
插入对象元素
//自定义数据类型
class Person
{
public:
Person(string name, int age)
{
this->m_Name = name;
this->m_Age = age;
}
string m_Name;
int m_Age;
};
vector<Person> v;
Person p1("aaa", 10);
Person p2("bbb", 20);
//插入对象
v.push_back(p1);
v.push_back(p2);
遍历元素
//遍历元素
vector<int>::iterator itBegin = v.begin(); //v.begin() 起始迭代器,指向容器中第一个数据
vector<int>::iterator itEnd = v.end(); //v.end();结束迭代器,指向的是容器中最后一个元素的下一个位置
//遍历方式1
for (; begin != end; begin++)
{
cout<<"item=" <<*begin <<endl;
}
void myprint(int va){
cout<<va<<endl;
}
//遍历方式2
for_each(v.begin(),v.end(),myprint);
vector常用赋值操作
assign(beg, end);//将[beg, end)区间中的数据拷贝赋值给本身。
assign(n, elem);//将n个elem拷贝赋值给本身。
vector& operator=(const vector &vec);//重载等号操作符
swap(vec);// 将vec与本身的元素互换。
vector<int>v3;
v3.assign(v1.begin(), v1.end());
vector大小操作
size();//返回容器中元素的个数
empty();//判断容器是否为空
resize(int num);//重新指定容器的长度为num,若容器变长,则以默认值填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。
resize(int num, elem);//重新指定容器的长度为num,若容器变长,则以elem值填充新位置。如果容器变短,则末尾超出容器长>度的元素被删除。
capacity();//容器的容量
reserve(int len);//容器预留len个元素长度,预留位置不初始化,元素不可访问。
reverse 翻转
v1.front()
v1.back()
2.2 deque
以数组为核心机制的双组集合,数组前后都可以添加数据,当需要扩容时,在对象的末端添加固定长度的数组对象。
2.2.1 deque构造函数
deque<T> deqT;//默认构造形式
deque(beg, end);//构造函数将[beg, end)区间中的元素拷贝给本身。
deque(n, elem);//构造函数将n个elem拷贝给本身。
deque(const deque &deq);//拷贝构造函数。
2.2.2deque赋值操作
assign(beg, end);//将[beg, end)区间中的数据拷贝赋值给本身。
assign(n, elem);//将n个elem拷贝赋值给本身。
deque& operator=(const deque &deq); //重载等号操作符
swap(deq);// 将deq与本身的元素互换
2.2.3deque大小操作
deque.size();//返回容器中元素的个数
deque.empty();//判断容器是否为空
deque.resize(num);//重新指定容器的长度为num,若容器变长,则以默认值填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。
deque.resize(num, elem); //重新指定容器的长度为num,若容器变长,
则以elem值填充新位置,如果容器变短,则末尾超出容器长度的元素被删除。
2.2.4 deque双端插入和删除操作
push_back(elem);//在容器尾部添加一个数据
push_front(elem);//在容器头部插入一个数据
pop_back();//删除容器最后一个数据
pop_front();//删除容器第一个数据
2.2.5 deque数据存取
at(idx);//返回索引idx所指的数据,如果idx越界,抛出out_of_range。
operator[];//返回索引idx所指的数据,如果idx越界,不抛出异常,直接出错。
front();//返回第一个数据。
back();//返回最后一个数据
2.2.6 deque插入操作
insert(pos,elem);//在pos位置插入一个elem元素的拷贝,返回新数据的位置。
insert(pos,n,elem);//在pos位置插入n个elem数据,无返回值。
insert(pos,beg,end);//在pos位置插入[beg,end)区间的数据,无返回值。
2.2.7 deque删除操作
clear();//移除容器的所有数据
erase(beg,end);//删除[beg,end)区间的数据,返回下一个数据的位置。
erase(pos);//删除pos位置的数据,返回下一个数据的位置。
sort(v.begin,v.end) 默认升序排序
3.stack
stack构造函数
stack<T> stkT;//stack采用模板类实现, stack对象的默认构造形式:
stack(const stack &stk);//拷贝构造函数
stack赋值操作
stack& operator=(const stack &stk);//重载等号操作符
stack数据存取操作
push(elem);//向栈顶添加元素
pop();//从栈顶移除第一个元素
top();//返回栈顶元素
3.4.3.4 stack大小操作
empty();//判断堆栈是否为空
size();//返回堆栈的大小
4.queue
构造函数
queue& operator=(const queue &que);//重载等号操作符
入队
Q.push(p1);
Q.empty()
Q.front()//队首
Q.back()//队尾
Q.size()
出队
Q.pop();
5.list
list构造函数
list<T> lstT;//list采用采用模板类实现,对象的默认构造形式:
list(beg,end);//构造函数将[beg, end)区间中的元素拷贝给本身。
list(n,elem);//构造函数将n个elem拷贝给本身。
list(const list &lst);//拷贝构造函数。
list数据元素插入
push_back(elem);//在容器尾部加入一个元素
push_front(elem);//在容器开头插入一个元素
insert(pos,elem);//在pos位置插elem元素的拷贝,返回新数据的位置。
insert(pos,n,elem);//在pos位置插入n个elem数据,无返回值。
insert(pos,beg,end);//在pos位置插入[beg,end)区间的数据,无返回值。
删除元素
clear();//移除容器的所有数据
erase(beg,end);//删除[beg,end)区间的数据,返回下一个数据的位置。
erase(pos);//删除pos位置的数据,返回下一个数据的位置。
remove(elem);//删除容器中所有与elem值匹配的元素。
pop_back();//删除容器中最后一个元素
pop_front();//从容器开头移除第一个元素
6.set
set构造函数
set<T> st;//set默认构造函数:
mulitset<T> mst; //multiset默认构造函数:
set(const set &st);//拷贝构造函数
set赋值操作
set& operator=(const set &st);//重载等号操作符
swap(st);//交换两个集合容器
set大小操作
size();//返回容器中元素的数目
empty();//判断容器是否为空
set插入和删除操作
insert(elem);//在容器中插入元素。
clear();//清除所有元素
erase(pos);//删除pos迭代器所指的元素,返回下一个元素的迭代器。
erase(beg, end);//删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。
erase(elem);//删除容器中值为elem的元素。
7.map
map构造函数
map<T1, T2> mapTT;//map默认构造函数:
map(const map &mp);//拷贝构造函数
map赋值操作
map& operator=(const map &mp);//重载等号操作符
swap(mp);//交换两个集合容器
map大小操作
size();//返回容器中元素的数目
empty();//判断容器是否为空
map插入数据元素操作
map.insert(...); //往容器插入元素,返回pair<iterator,bool>
map<int, string> mapStu;
// 第一种 通过pair的方式插入对象
mapStu.insert(pair<int, string>(3, "小张"));
// 第二种 通过pair的方式插入对象
mapStu.inset(make_pair(-1, "校长"));
// 第三种 通过value_type的方式插入对象
mapStu.insert(map<int, string>::value_type(1, "小李"));
// 第四种 通过数组的方式插入值
mapStu[3] = "小刘";
mapStu[5] = "小王";
map查找操作
find(key);//查找键key是否存在,若存在,返回该键的元素的迭代器;/若不存在,返回map.end();
count(keyElem);//返回容器中key为keyElem的对组个数。对map来说,要么是0,要么是1。对multimap来说,值可能大于1。
lower_bound(keyElem);//返回第一个key>=keyElem元素的迭代器。
upper_bound(keyElem);//返回第一个key>keyElem元素的迭代器。
equal_range(keyElem);//返回容器中key与keyElem相等的上下限的两个迭代器。
multimap
3.string 对象
构造函数
string();//创建一个空的字符串 例如: string str;
string(const string& str);//使用一个string对象初始化另一个string对象
string(const char* s);//使用字符串s初始化
string(int n, char c);//使用n个字符c初始化
string str;
string str2(str);
string str3("abc");
string str4(10, 'a');
string基本赋值操作
string& operator=(const char* s);//char*类型字符串 赋值给当前的字符串
string& operator=(const string &s);//把字符串s赋给当前的字符串
string& operator=(char c);//字符赋值给当前的字符串
string& assign(const char *s);//把字符串s赋给当前的字符串
string& assign(const char *s, int n);//把字符串s的前n个字符赋给当前的字符串
string& assign(const string &s);//把字符串s赋给当前字符串
string& assign(int n, char c);//用n个字符c赋给当前字符串
string& assign(const string &s, int start, int n);//将s从start开始n个字符赋值给字符串
string存取字符操作
char& operator[](int n);//通过[]方式取字符
char& at(int n);//通过at方法获取字符
string str = "hello world";
//[]和at区别,[]访问越界 直接挂掉 , at访问越界 抛出out_of_range异常
for (int i = 0; i < str.size();i++)
{
//cout << str[i] << endl;
cout << str.at(i) << endl;
}
string拼接操作
string& operator+=(const string& str);//重载+=操作符
string& operator+=(const char* str);//重载+=操作符
string& operator+=(const char c);//重载+=操作符
string& append(const char *s);//把字符串s连接到当前字符串结尾
string& append(const char *s, int n);//把字符串s的前n个字符连接到当前字符串结尾
string& append(const string &s);//同operator+=()
string& append(const string &s, int pos, int n);//把字符串s中从pos开始的n个字符连接到当前字符串结尾
string& append(int n, char c);//在当前字符串结尾添加n个字符c
string查找和替换
int find(const string& str, int pos = 0) const; //查找str第一次出现位置,从pos开始查找
int find(const char* s, int pos = 0) const; //查找s第一次出现位置,从pos开始查找
int find(const char* s, int pos, int n) const; //从pos位置查找s的前n个字符第一次位置
int find(const char c, int pos = 0) const; //查找字符c第一次出现位置
int rfind(const string& str, int pos = npos) const;//查找str最后一次位置,从pos开始查找
int rfind(const char* s, int pos = npos) const;//查找s最后一次出现位置,从pos开始查找
int rfind(const char* s, int pos, int n) const;//从pos查找s的前n个字符最后一次位置
int rfind(const char c, int pos = 0) const; //查找字符c最后一次出现位置
string& replace(int pos, int n, const string& str); //替换从pos开始n个字符为字符串str
string& replace(int pos, int n, const char* s); //替换从pos开始的n个字符为字符串s
string比较操作
//compare函数在>时返回 1,<时返回 -1,==时返回 0。比较区分大小写,比较时参考字典顺序,排越前面的越小。大写的A比小写的a小。
int compare(const string &s) const;//与字符串s比较
int compare(const char *s) const;//与字符串s比较
string子串
string substr(int pos = 0, int n = npos) const;//返回由pos开始的n个字符组成的字符串
string插入和删除操作
string& insert(int pos, const char* s); //插入字符串
string& insert(int pos, const string& str); //插入字符串
string& insert(int pos, int n, char c);//在指定位置插入n个字符c
string& erase(int pos, int n = npos);//删除从Pos开始的n个字符
string和c-style字符串转换
const char * str = "abcd";
//const char * 转为 string
string s(str);
//string 转为 const char *
const char * str2 = s.c_str();
//const char * 可以隐式类型转换为 string
doWork(str2);
//string 不可以隐式类型转换为 const char*
//doWork2(s);
小写、大写字母转换
string str = "abcdEFg";
for (int i = 0; i < str.size();i++)
{
//str[i] = toupper(str[i]);
str[i] = tolower(str[i]);
}
cout << str << endl;
函数对象-仿函数
重载函数调用操作符的类,其对象常称为函数对象(function object)。重载了‘()’操作符的对象,叫函数对象,也叫函数符,
操作符重载的时候,要求一个参数,又叫一元仿函数
要两个参数,就要二元仿函数。
1、函数对象通常不定义构造函数和析构函数,所以在构造和析构时不会发生任何问题,避免了函数调用的运行时问题。
2、函数对象超出普通函数的概念,函数对象可以有自己的状态
3、函数对象可内联编译,性能好。
4、模版函数对象使函数对象具有通用性
class myprint{
public:
void operator()(string name){
cout<< name<<endl;
}
};
myprint my;
myprint my("world");
谓词
生成器是不用参数就可以调用的函数符。
一元函数是用一个参数可以调用的函数符。
二元函数是用两个参数可以调用的函数符。
返回bool值得一元函数是谓词
返回bool值得二元函数是二元谓词
内建函数对象
STL提供的一些函数对象,分为算数类、关系类、逻辑运算类
。使用内建函数对象,引入头文件#include <functional>
- 算数类
negate是一元运算,其他都是二元运算。所谓二元运算,就是需要2个参数。
template<class T> T plus<T>//加法仿函数
template<class T> T minus//减法仿函数
template<class T> T multiplies//乘法仿函数
template<class T> T divides//除法仿函数
template<class T> T modulus//取模仿函数
template<class T> T negate//取反仿函数
eg:加法仿函数
void test02()
{
plus<int> p;
cout << p(10, 10) << endl;
}
- 关系类
都是二元运算。
template<class T> bool equal_to//等于
template<class T> bool not_equal_to//不等于
template<class T> bool greater//大于
template<class T> bool greater_equal//大于等于
template<class T> bool less//小于
template<class T> bool less_equal//小于等于
- 逻辑运算类
not为一元运算,其余为二元运算。
template<class T> bool logical_and//逻辑与
template<class T> bool logical_or//逻辑或
template<class T> bool logical_not//逻辑非
lambda表达式
距离,简洁,效率,功能
bool f3(int x){ return x%3==0;}
等同于
[](int x){return x%3==0;}
- [] 代替了函数名
- 返回值,由decltyp自行推断,如没有返回值,为void
count3 = std::count_if(v.begin(),v.end(),[](int x){return x%3==0;})
使用整个lambda表达式替换函数指针或者函数符构造函数
注意:仅当lambda表达式由一条返回语句组成时,自动类型推断才有效。
适配器(包装器)
常用算法
算法
遍历算法
1.foreach遍历
class MyPrint
{
public:
void operator()(int val)
{
cout << val << endl;
m_Count++;
}
int m_Count = 0;
};
vector<int>v;
for (int i = 0; i < 10;i++)
{
v.push_back(i);
}
MyPrint print = for_each(v.begin(), v.end(), MyPrint());
cout << "print.count = " << print.m_Count << endl;
2.foreach 绑定参数输入
//for_each可以绑定参数输出
//int,int,void: 第一个参数,第二个参数,返回值
class MyPrint2 :public binary_function<int,int,void>
{
public:
void operator()(int val , int start) const
{
cout << val << endl;
}
};
vector<int>v;
for (int i = 0; i < 10;i++)
{
v.push_back(i);
}
MyPrint print = for_each(v.begin(), v.end(), MyPrint());
cout << "print.count = " << print.m_Count << endl;
3.transform算法 将指定容器区间元素搬运到另一容器中
//transform算法 将指定容器区间元素搬运到另一容器中
class MyTransform
{
public:
int operator()(int val)
{
return val + 10000;
}
};
void test03()
{
vector<int>v;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
vector<int>v2;
v2.resize(v.size());
transform(v.begin(), v.end(), v2.begin(), MyTransform());
//lambda表达式
for_each(v2.begin(), v2.end(), [](int val){cout << val << " "; });
}
查找算法
find算法 查找元素
/*find算法 查找元素
@param beg 容器开始迭代器
@param end 容器结束迭代器
@param value 查找的元素
@return 返回查找元素的位置
*/
vector<int>v;
for (int i = 0; i < 10;i++)
{
v.push_back(i);
}
vector<int>::iterator pos = find(v.begin(), v.end(), 5);
if (pos != v.end())
{
cout << "找到了元素:" << *pos << endl;
}
find_if算法 条件查找
@param beg 容器开始迭代器
@param end 容器结束迭代器
@param callback 回调函数或者谓词(返回bool类型的函数对象)
@return bool 查找返回true 否则false
Person * p = new Person("bbb", 20);
vector<Person *>::iterator pos = find_if(v.begin(), v.end(), bind2nd( MyComparePerson() ,p) );
if (pos != v.end())
{
cout << "找到了元素--- 姓名: " << (*pos)->m_Name << " 年龄: " << (*pos)->m_Age << endl;
}
else
{
cout << "未找到" << endl;
}
adjacent_find算法 查找相邻重复元素
vector<int>v;
v.push_back(3);
v.push_back(2);
v.push_back(300);
v.push_back(300);
v.push_back(6);
v.push_back(3);
vector<int>::iterator ret = adjacent_find(v.begin(), v.end());
binary_search算法 二分查找法
注意:容器一定要有序
的
vector<int>v;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
//v.push_back(4); 必须是有序序列,如果无效 结果未知
bool ret=binary_search(v.begin(), v.end(), 2);
count算法 统计元素出现次数
@param beg 容器开始迭代器
@param end 容器结束迭代器
@param value回调函数或者谓词(返回bool类型的函数对象)
@return int返回元素个数
vector<int>v;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
v.push_back(3);
v.push_back(3);
v.push_back(3);
int num = count(v.begin(), v.end(), 3);
排序算法
merge算法 容器元素合并,并存储到另一容器中
注意 : 两个容器必须是有序的,顺序要一致
vector<int>vTarget; //目标容器
vTarget.resize(v1.size() + v2.size());
merge(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin());
for_each(vTarget.begin(), vTarget.end(), [](int val){cout << val << " "; });
sort 排序
sort(v.begin(), v.end(), greater<int>());
random_shuffle算法 对指定范围内的元素随机调整次序
random_shuffle(v.begin(), v.end());
for_each(v.begin(), v.end(), [](int val){cout << val << " "; });
reverse算法 反转指定范围的元素
reverse(v.begin(), v.end());
cout << "反转后打印: " << endl;
for_each(v.begin(), v.end(), [](int val){cout << val << " "; });
拷贝和替换算法
copy算法 将容器内指定范围的元素拷贝到另一容器中
vector<int>v2;
v2.resize(v.size());
copy(v.begin(), v.end(), v2.begin());
//replace算法 将容器内指定范围的旧元素修改为新元素
//replace_if(iterator beg, iterator end, _callback, newvalue) 按条件替换
//将容器中的3替换为 3000
replace(v.begin(), v.end(), 3, 3000);
class MyReplace
{
public:
bool operator()(int val)
{
return val > 3;
}
};
//将容器中所有大于3的都替换为 30000;
replace_if(v.begin(), v.end(), MyReplace() , 30000);
swap交换
cout << "交换数据后:" << endl;
swap(v, v2);
//遍历打印
copy(v.begin(), v.end(), ostream_iterator<int>(cout, " "));
cout << endl;
常用算数算法
引入#include //accumulate算法头文件
accumulate算法
//accumulate算法 计算容器元素累计总和
void test01()
{
vector<int>v;
for (int i = 0; i <= 100;i++)
{
v.push_back(i);
}
int num = accumulate(v.begin(), v.end(),1000); // 参数3代表 累加起始值
cout << "num = " << num << endl;
}
fill算法 向容器中添加元素
//fill算法 向容器中添加元素
fill(v.begin(), v.end(), 100);
for_each(v.begin(), v.end(), [](int val){cout << val << " "; });
cout << endl;