注:此博文不具有教学意义,只作为自己复习用。
目录
1.1.1 序列式容器(Sequence Contaciers)
1.1.2 关联式容器(Associated Containers)
4.2.3 find_first_of:在a数组中,发现b数组元素的位置
4.2.4 adjacent_find:当前容器首次相邻元素的位置
4.5 STL变异算法(二):swap算法:copy算法重定向到屏幕
4.6 STL变异算法(三):transform算法--加密的案例
4.8 STL变异算法(五):unique算法实现文本单词统计
4.9 STL变异算法(六):sort算法与binary算法
1. STL六大组件
1.1 容器(Container):用来管理一组元素
1.1.1 序列式容器(Sequence Contaciers)
- 每个元素都有归固定位置--取决于插入实际和地点,和元素值无关
- vector,deque,list
1.1.2 关联式容器(Associated Containers)
- 元素位置取决于特定排序准则,与插入顺序无关
- set,multiset,map,multimap
1.2 算法(Algorithm)
1.3 迭代器(Iterator)
1.4 仿函数(Function object)
1.5 适配器(Adaptor)
1.6 空间配置器(Allocator)
2. 序列式容器
2.1 Vector
- 动态数组,在堆中分配内存,元素连续存放。
- 即使减少大小,内存也不会释放。
- 通常情况下,不会移动内存。
- 只有保留内存不够的时候,才会对中间和开始处的元素进行移动,如下:
成倍扩容:
再次成倍扩容:
2.2 Deque
- deque,为“double-ended-queue”的缩写
- 可以随机存取元素(用索引)
- 数组头部和尾部添加或一处元素都非常快速,但是在中间插入元素比较费时
看出deque与vector分配空间的区别:
- vector:一块独立的连续存放的内存空间
- 建立空间
- 填充数据
- 空间不够,重新分配更大的空间
- 复制原空间内容
- 删除原空间
- 添加新数据
- deque:由多个分段连续的内存空间组成
- 建立空间
- 填充数据
- 建立新空间
- 添加新数据
2.2.1 简单例子:使用deque模拟队列
template<class T>
class MyQueue {
deque<T>d;
public:
void push(const T& x) {
d.push_back(x);
}
void pop() {
d.pop_front();
}
int size() {
return d.size();
}
bool empty() {
return d.empty();
}
T& front() {
return *d.begin();
}
T& back() {
return *(d.end() - 1);
}
};
2.2.2 简单例子:设计一个具有固定大小的stack
template<class T,class Container=deque<T>>
class MyStack :public stack<T, Container> {
public:
MyStack(int size) :m_MaxSize(size) {
}
void push(const T& x) {
if (stack<T, Container>::size() < m_MaxSize) {
stack<T, Container>::push(x);
}
else {
cout << "栈空间已满" << x << "未进栈" << endl;
}
}
private:
int m_MaxSize;
};
2.3 List
- 双向链表
- 不提供随机存取
- 在任何位置上执行插入或删除都非常迅速,内部只需调整一下指针
这里模拟一个例子:
由两个文本文件:日志文件
搜集了若干个机器的基础数据
包含机器号,机器名,机器的连续运转时间
由于某种原因,两个日志可能有一些重复的记录:
①把两个日志文件的数据映射成两个list元素
②对这两个日志按机器号升序排序
③合并两个已排好序的list容器元素
④利用unique函数去掉机器号重复的元素
class Machine {
public:
Machine(string strNo,string strName,int total)
:m_strNo(strNo),m_strName(strName),m_nTotal(total)
{}
bool operator<(Machine& m) {
return m_strNo < m.GetNo();
}
bool operator==(Machine& m) {
return m_strNo == m.GetNo();
}
string GetNo() { return m_strNo; }
string GetName() { return m_strName; }
int GetTotal() { return m_nTotal; }
private:
string m_strNo;//机器号
string m_strName;//机器名
int m_nTotal;//连续工作时间
};
ostream& operator<<(ostream& os, Machine& m) {
os << m.GetNo() << "\t" << m.GetName() << "\t" << m.GetTotal();
return os;
}
typedef list<Machine>LISTMACHINE;
class MachineMgr {
public:
bool Add(const Machine& m) {
m_list.push_back(m);
return true;
}
bool Merge(MachineMgr& machMgr) {
this->m_list.sort();
machMgr.m_list.sort();
this->m_list.merge(machMgr.m_list);
this->m_list.unique();
return true;
}
private:
LISTMACHINE m_list;
};
3.关联式容器
3.1 Set/Multiset
- 内部元素依据值自动排序
- Set内相同数值元素只出现一次,Multiset内可包含多个数值相同的元素
- 内部由二叉树(红黑树)实现,便于查找
3.2 Map/Multimap
- map的元素是成对的key/value,内部元素依据key自动排序
- map内相同key只能出现一次,一个key对应一个value;
- multimap一个key可对应多个value
- 内部由红黑树实现
c++中map详解_不会编程的小猿的博客-CSDN博客_c++map
4.STL:Algorithm(算法)
- 泛型算法通则:
- 所有算法的前两个参数都是一对 iterators:[first,last),用来指出容器内一个范围内的元素
- 每个算法的声明中,都表现出它所需要的最低层次的iterator类型
- 大部分算法都可以用function object来更改准则。function object又称functor:
4.0 引论和例子
算法都是施加在容器上,如果我们要对容器中某一范围的元素进行操作,那么我们使用仿函数。
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
using namespace std;
template<class T>
class Add {
public :
void operator()(T& t) {
t *= 2;
}
};
int main() {
vector<int>v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
//Add类仿函数
Add<int>myAdd;
for_each(v.begin(), v.end(), myAdd);
for (auto& it : v) {
cout << it << " ";
}
cout << endl;
//lambda匿名仿函数
auto fun = [](int a) {a *= 3; };
for_each(v.begin(), v.end(), fun);
for (auto& it : v) {
cout << it << " ";
}
return 0;
}
4.1 STL非变异算法(一):for_each
传入一个function object而不是函数指针,可以实现多种功能,比如Max,Sum,Min
unary_function和binay_function_suyinfan的博客-CSDN博客
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
template<class T,class _outPara>
class PrintInfo :public unary_function<T, _outPara> {
public:
PrintInfo() :count(0), Sum(0) { }
T GetSum() { return Sum; }
T GetMax() { return Max; }
T GetMin() { return Min; }
_outPara operator()(T x) {
if (count == 0) {
Max = x;
Min = x;
}
else {
if (Max < x) {
Max = x;
}
if (Min > x) {
Min = x;
}
}
Sum += x;
count++;
}
private:
T Sum;
T Max;
T Min;
int count;
};
int main() {
float a[] = { 1.0,2.0,3.0,4.0,5.0,6.0 };
const int N = sizeof(a) / sizeof(float);
PrintInfo<float, void> p = for_each(a, a + N, PrintInfo<float, void>());
cout << "sum:" << p.GetSum() << endl;
cout << "max:" << p.GetMax() << endl;
cout << "min:" << p.GetMin() << endl;
return 0;
}
4.2 STL非变异算法(二):find
int a[] = { 1,2,2,3,4,4,5,6,7,1,2,3,4 };
int n = sizeof(a) / sizeof(int);
4.2.1 find
//第一个等于3
int* p1 = find(a, a + n, 3);
4.2.2 find_if:查找第一个满足条件的位置
bool myGreater(int temp) {
return temp > 4;
}
//出现第一个大于4
int* p2 = find_if(a, a + n, myGreater);
4.2.3 find_first_of:在a数组中,发现b数组元素的位置
//首次在a数组中,发现由b数组元素的位置
int b[] = { 7,8,9 };
int n1 = sizeof(b) / sizeof(int);
int* p3 = find_first_of(a, a + n,b, b + n1);
4.2.4 adjacent_find:当前容器首次相邻元素的位置
//当前容器中首次相邻元素的位置
int* p4 = adjacent_find(a, a + n);
4.2.5 find_end:最后一次匹配c数组的位置
//最后一次匹配c数组的位置
int c[] = { 2,3 };
int nc = sizeof(c) / sizeof(int);
int* p5 = find_end(a, a + n, c, c + n);
4.2.6 search:首次匹配c数组的位置
//首次匹配sc数组的位置
int* p6 = search(a, a + n, c, c + n);
4.3 STL非变异算法(三):pair
int A1[] = { 3,1,4,1,5,9,3 };
int A2[] = { 3,1,4,2,8,5,7 };
const int N = sizeof(A1) / sizeof(int);
pair<int*, int*>res = mismatch(A1, A1 + N, A2);
cout << "首次出现不一样的位置" << res.first - A1 << endl;
cout << "对应的数值" << *(res.first) << "," << *(res.second) << endl;
4.4 STL变异算法(一):copy与迭代器的组合
int a[] = { 1,2,3,4,5 };
vector<int>v;
copy(a, a + 5, back_inserter(v));
4.5 STL变异算法(二):swap算法:copy算法重定向到屏幕
swap:基本数据类、数组、基本序列容器
数组:必须存在真实的空间,大小一定固定
基本序列:不需要相同的空间大小
int a2[] = { 1,3,5,7,9 };
int b2[] = { 2,4,6,8,10 };
swap_ranges(a2, a2 + 5, b2);
copy(a2,a2+5,ostream_iterator<int>(cout,"\t"));
cout << endl;
copy(b2,b2+5,ostream_iterator<int>(cout,"\t"));
4.6 STL变异算法(三):transform算法--加密的案例
template<class T>
class Encrypt {
};
template<>
class Encrypt<string> {
string operator()(const string& src) {
string s = src;
int len = s.size();
//加密
for (auto it : s) {
it = it + 1;
}
return s;
}
};
string strText;
vector<string>v;
ifstream in("D:\Encrypt.txt");
while (!in.eof()) {
getline(in, strText, '\n');
v.push_back(strText);
}
in.close();
transform(v.begin(), v.end(), back_inserter(v), Encrypt<string>());
copy(v.begin(), v.end(), ostream_iterator<string>(cout, "\n"));
4.7 STL变异算法(四):replace算法
int aa[] = { 2,3,4,5,2,2,-1 };
replace(aa, aa + 7, 2, 10);
copy(aa, aa + 7, ostream_iterator<int>(cout, "\t"));
4.8 STL变异算法(五):unique算法实现文本单词统计
unique:消除容器里相邻相等的元素
stricmp_墨子非阿萨德的博客-CSDN博客_stricmp
ifstream out("D:\\DesignPatterns\\Template_STL\\words.txt");
vector<string>v;
copy(istream_iterator<string>(out), istream_iterator<string>(), back_inserter(v));
cout << endl;
vector<string>vRes;
unique_copy(v.begin(), v.end(), back_inserter(vRes), MyStrComp);
copy(vRes.begin(), vRes.end(), ostream_iterator<string>(cout, "\n"));
4.9 STL变异算法(六):sort算法与binary算法
sort的迭代器是随机迭代器,list是双向迭代器:list.sort(),而不是 sort(list.begin(),list.end())
int a3[] = { 1,3,3,5,5,7,9,10 };
list<int>l(a3, a3 + 8);
bool bExsit = binary_search(l.begin(), l.end(), 5);
//第一个3
list<int>::iterator it = lower_bound(l.begin(), l.end(), 3);
if (it != l.end())cout << distance(l.begin(), it) << endl;
list<int>::iterator it1 = upper_bound(l.begin(), l.end(), 5);
if (it1 != l.end())cout << distance(l.begin(), --it1) << endl;