C++模板与STL(三):容器与算法

注:此博文不具有教学意义,只作为自己复习用。

目录

1. STL六大组件

1.1 容器(Container):用来管理一组元素 

1.1.1 序列式容器(Sequence Contaciers)

1.1.2 关联式容器(Associated Containers)

1.2 算法(Algorithm)

1.3 迭代器(Iterator)

1.4 仿函数(Function object)

1.5 适配器(Adaptor)

1.6 空间配置器(Allocator)

2. 序列式容器

2.1 Vector

2.2 Deque

2.2.1 简单例子:使用deque模拟队列

2.2.2 简单例子:设计一个具有固定大小的stack

2.3 List

3.关联式容器

3.1 Set/Multiset

3.2 Map/Multimap

4.STL:Algorithm(算法)

4.0 引论和例子

4.1 STL非变异算法(一):for_each

4.2 STL非变异算法(二):find

4.2.1 find

4.2.2 find_if:查找第一个满足条件的位置

4.2.3 find_first_of:在a数组中,发现b数组元素的位置

4.2.4 adjacent_find:当前容器首次相邻元素的位置

4.2.5 find_end:最后一次匹配c数组的位置

4.2.6 search:首次匹配c数组的位置

4.3 STL非变异算法(三):pair

4.4 STL变异算法(一):copy与迭代器的组合

4.5 STL变异算法(二):swap算法:copy算法重定向到屏幕

4.6 STL变异算法(三):transform算法--加密的案例

4.7 STL变异算法(四):replace算法

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;

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值