栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

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

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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 MyQueue {
	dequed;
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 MyStack :public stack {
public:
	MyStack(int size) :m_MaxSize(size) {

	}
	void push(const T& x) {
		if (stack::size() < m_MaxSize) {
			stack::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 listLISTMACHINE;
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 
#include 
#include 
#include 

using namespace std;

template
class Add {
public	:
	void operator()(T& t) {
		t *= 2;
	}
};

int main() {
	vectorv;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	//Add类仿函数
	AddmyAdd;
	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 
#include 
#include 
using namespace std;

template
class PrintInfo :public unary_function {
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 p = for_each(a, a + N, PrintInfo());
	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);
	pairres = 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 };
	vectorv;
	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(cout,"t"));
	cout << endl;
	copy(b2,b2+5,ostream_iterator(cout,"t"));

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

};

template<>
class Encrypt {
	string operator()(const string& src) {
		string s = src;
		int len = s.size();
		//加密
		for (auto it : s) {
			it = it + 1;
		}
		return s;
	}
};
	string strText;
	vectorv;
	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());
	copy(v.begin(), v.end(), ostream_iterator(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(cout, "t"));

4.8 STL变异算法(五):unique算法实现文本单词统计

unique:消除容器里相邻相等的元素

stricmp_墨子非阿萨德的博客-CSDN博客_stricmp

	ifstream out("D:\DesignPatterns\Template_STL\words.txt"); 
	vectorv;
	copy(istream_iterator(out), istream_iterator(), back_inserter(v));
	cout << endl;

	vectorvRes;
	unique_copy(v.begin(), v.end(), back_inserter(vRes), MyStrComp);
	copy(vRes.begin(), vRes.end(), ostream_iterator(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 };
	listl(a3, a3 + 8);
	bool bExsit = binary_search(l.begin(), l.end(), 5);
	//第一个3
	list::iterator it = lower_bound(l.begin(), l.end(), 3);
	if (it != l.end())cout << distance(l.begin(), it) << endl;

	list::iterator it1 = upper_bound(l.begin(), l.end(), 5);
	if (it1 != l.end())cout << distance(l.begin(), --it1) << endl;

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1039379.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号