c++ 提高4 map容器 共性机制 使用时机 比较| STL算法 算法基础仿函数 谓词 函数适配器 遍历算法

【本文谢绝转载】

《大纲》

STL
	容器
		map 容器的4中初始化 遍历
		map容器 元素的删除观测map.insert返回值,方法123,已存在就报错,初始化方法4会覆盖
		map的查找,异常处理
		map容器的range返回两个迭代器
		multimap案例,按照部门_增删员工信息
	容器共性机制
	把对象放到容器中,会自动执行拷贝构造函数
	各个容器的使用时机
	vector与deque的比较:

	算法
		算法基础
			函数对象(仿函数)
			函数对象 与普通函数的区别:--  相同之处
			函数对象 与普通函数的区别:--  不同之处
			分清楚STL算法返回值,是迭代器还是函数对象,是STL算法入门的标志
			一元谓词函数 案例,查找能够4整除的数
			二元对象,二元谓词 案例
			二元函数  二元谓词的应用
			二元函数  二元谓词在 集合中的应用 -- find函数默认不支持忽略大小写
			二元函数  二元谓词在 集合中的应用 -- 让find函数支持忽略大小写
			预定义函数对象  与 函数适配器
			函数适配器综合案例 统计大于8的元素个数,预定于与谓词 band2nd 与 not
		遍历算法:
			1 容器的遍历1  迭代器
			2 容器的遍历  自定义函数
			3 容器的遍历 仿函数
			transform 使用回调函数修改自己的容器
			transform 使用预定义函数修改自己的容器
			使用函数适配器 与 函数对象
			利用transform ,使用适配器,将计算结果储存到list容器
			直接将结果输出到屏幕
			transform 与 for_each比较	

map 容器的4中初始化 遍历

[email protected]://990487026.blog.51cto.com~/c++$ cat main.cpp 
#include <iostream>
#include <stdio.h>
using namespace std;
#include <map> 
#include <string> 

int main()
{
	map <int,string> map1;
	//方法1
	map1.insert(pair <int,string>(1,"Linux"));
	map1.insert(pair <int,string>(2,"Mac"));

	//方法2
	map1.insert(make_pair(3,"debian"));
	map1.insert(make_pair(4,"ubuntu"));

	//方法3
	map1.insert(map<int ,string>::value_type(5,"redhat"));
	map1.insert(map<int ,string>::value_type(6,"centos"));

	//方法4
	map1[7] = "VIM";
	map1[8] = "tcpdump";
	map1[8] = "ssh";	//会覆盖tcpdump的值

	//遍历
	for(map<int,string>::iterator it = map1.begin();it!= map1.end();it++)
	{
		//map会返回两个元素
		cout << it->first << "\t" << it->second << endl;

	}
	return 0;
}
[email protected]://990487026.blog.51cto.com~/c++$ g++  -g -o run main.cpp && ./run 
1	Linux
2	Mac
3	debian
4	ubuntu
5	redhat
6	centos
7	VIM
8	ssh
[email protected]://990487026.blog.51cto.com~/c++$

map容器 元素的删除

[email protected]://990487026.blog.51cto.com~/c++$ cat main.cpp 
#include <iostream>
#include <stdio.h>
using namespace std;
#include <map> 
#include <string> 

int main()
{
	map <int,string> map1;
	//方法1
	map1.insert(pair <int,string>(1,"Linux"));
	map1.insert(pair <int,string>(2,"Mac"));

	//方法2
	map1.insert(make_pair(3,"debian"));
	map1.insert(make_pair(4,"ubuntu"));

	//方法3
	map1.insert(map<int ,string>::value_type(5,"redhat"));
	map1.insert(map<int ,string>::value_type(6,"centos"));

	//方法4
	map1[7] = "VIM";
	map1[8] = "tcpdump";
	map1[8] = "ssh";	//会覆盖tcpdump的值

	//遍历
	for(map<int,string>::iterator it = map1.begin();it!= map1.end();it++)
	{
		//map会返回两个元素
		cout << it->first << "\t" << it->second << endl;

	}

	//容器元素的删除
	while(!map1.empty())
	{
		map<int,string>::iterator it  = map1.begin();
		//cout << it->first << "\t" << it->second << endl;
		map1.erase(it);
	}
	//容器元素删除的检查
	while(!map1.empty())
	{
		map<int,string>::iterator it  = map1.begin();
		cout << it->first << "\t" << it->second << endl;
		//map1.erase(it);
	}

	return 0;
}
[email protected]://990487026.blog.51cto.com~/c++$ g++  -g -o run main.cpp && ./run 
1	Linux
2	Mac
3	debian
4	ubuntu
5	redhat
6	centos
7	VIM
8	ssh
[email protected]://990487026.blog.51cto.com~/c++$

观测map.insert返回值,方法123,已存在就报错,方法4会覆盖

[email protected]://990487026.blog.51cto.com~/c++$ cat main.cpp 
#include <iostream>
#include <stdio.h>
using namespace std;
#include <map> 
#include <string> 

int main()
{
	map <int,string> map1;
	//方法1
	pair<map<int,string>::iterator,bool> mypair1 =  map1.insert(pair <int,string>(1,"Linux"));
	map1.insert(pair <int,string>(2,"Mac"));

	//方法2
	pair<map<int,string>::iterator,bool> mypair2 =  map1.insert(make_pair(3,"debian"));
	map1.insert(make_pair(4,"ubuntu"));

	//方法3
	pair<map<int,string>::iterator,bool> mypair5 = map1.insert(map<int ,string>::value_type(5,"redhat"));
	if(mypair5.second == true)
	{
		cout << "插入成功\t" << mypair5.first->first << "\t" << mypair5.first->second << endl;
	}
	else
	{
		cout << "5 插入失败\n";
	}
	pair<map<int,string>::iterator,bool> mypair6 = map1.insert(map<int ,string>::value_type(5,"redhat"));
	if(mypair6.second == true)
	{
		cout << "插入成功\t" << mypair6.first->first << "\t" << mypair6.first->second << endl;
	}
	else
	{
		cout << "6 插入失败\n";
	}

	//方法4
	map1[7] = "VIM";
	map1[8] = "tcpdump";
	map1[8] = "ssh";	//会覆盖tcpdump的值

	//遍历
	for(map<int,string>::iterator it = map1.begin();it!= map1.end();it++)
	{
		//map会返回两个元素
		cout << it->first << "\t" << it->second << endl;

	}

	//容器元素的删除
	while(!map1.empty())
	{
		map<int,string>::iterator it  = map1.begin();
		//cout << it->first << "\t" << it->second << endl;
		map1.erase(it);
	}
	//容器元素删除的检查
	while(!map1.empty())
	{
		map<int,string>::iterator it  = map1.begin();
		cout << it->first << "\t" << it->second << endl;
		//map1.erase(it);
	}

	return 0;
}
[email protected]://990487026.blog.51cto.com~/c++$ g++  -g -o run main.cpp && ./run 
插入成功	5	redhat
6 插入失败
1	Linux
2	Mac
3	debian
4	ubuntu
5	redhat
7	VIM
8	ssh
[email protected]://990487026.blog.51cto.com~/c++$

map的查找,异常处理

[email protected]://990487026.blog.51cto.com~/c++$ cat main.cpp 
#include <iostream>
#include <stdio.h>
using namespace std;
#include <map> 
#include <string> 

int main()
{
	map <int,string> map1;
	map1[7] = "VIM";
	map1[8] = "tcpdump";

	map <int ,string> ::iterator it  = map1.find(7);
	if(it == map1.end())
	{
		cout << "没有找到" << endl;;
	}
	else
	{
		cout << it->first <<"\t" << it->second << endl;
	}

	map <int ,string> ::iterator it2  = map1.find(99);
	if(it2 == map1.end())
	{
		cout << "没有找到" << endl;;
	}
	else
	{
		cout << it2->first <<"\t" << it2->second << endl;
	}

	return 0;
}
[email protected]://990487026.blog.51cto.com~/c++$ g++  -g -o run main.cpp && ./run 
7	VIM
没有找到
[email protected]://990487026.blog.51cto.com~/c++$

map容器的range返回两个迭代器

[email protected]://990487026.blog.51cto.com~/c++$ cat main.cpp 
#include <iostream>
#include <stdio.h>
using namespace std;
#include <map> 
#include <string> 

int main()
{
	map <int,string> map1;
	map1[6] = "Kernel";
	map1[7] = "VIM";
	map1[8] = "tcpdump";
	map1[9] = "systemd";

	pair<map<int,string>::iterator, map<int,string>::iterator> mapair1 = map1.equal_range(7);//返回两个迭代器的位置
	//第一个迭代器的位置 >=5
	//第二个迭代器的位置 >5
	if(mapair1.first == map1.end())
	{
		cout << "第一个位置不存在\n";
	}
	else
	{
		cout << mapair1.first->first << "\t" << mapair1.first->second << endl;
	}

	if(mapair1.second == map1.end())
	{
		cout << "第二个位置不存在\n";
	}
	else
	{
		cout << mapair1.second->first << "\t" << mapair1.second->second << endl;
	}
	return 0;
}
[email protected]://990487026.blog.51cto.com~/c++$ g++  -g -o run main.cpp && ./run 
7	VIM
8	tcpdump
[email protected]://990487026.blog.51cto.com~/c++$

multimap案例,按照部门_增删员工信息

[email protected]://990487026.blog.51cto.com~/c++$ cat main.cpp 
#include <iostream>
#include <stdio.h>
using namespace std;
#include <map> 
#include <string> 

class Person
{

public:
	string name;
	int age;
	int tel;
	double saly;
};

int main()
{
	Person p1;	p1.name = "斯坦福";	p1.age = 11;	p1.saly = 1.1;
	Person p2;	p2.name = "麻省理工";	p2.age = 21;	p2.saly = 2.1;
	Person p3;	p3.name = "耶鲁";	p3.age = 31;	p3.saly = 3.1;
	Person p4;	p4.name = "剑桥";	p4.age = 41;	p4.saly = 4.1;
	Person p5;	p5.name = "清华";	p5.age = 51;	p5.saly = 5.1;

	multimap <string,Person> map2;
	//sale部门
	map2.insert(make_pair("sale",p1));
	map2.insert(make_pair("sale",p2));

	//研发部
	map2.insert(make_pair("development",p3));
	map2.insert(make_pair("development",p4));

	//财务部
	map2.insert(make_pair("financial",p5));
	//全部遍历
	for(multimap<string,Person>::iterator it = map2.begin();it!=map2.end();it++)
	{
		cout << it->first << "\t"<< it->second.name << "\t" << it->second.saly << endl;
	}
	cout << "全部遍历结束\n\n\n\n";

	cout << "development部门人数:" << map2.count("development") << endl;
	multimap<string,Person>::iterator it2 = map2.find("development");
	int num = map2.count("development");
	int tag = 0;
	while (it2 != map2.end() && tag < num)
	{
		cout << it2->first << "\t"<< it2->second.name << "\t" << it2->second.saly << endl;
		it2++;
		tag++;
	}

	return 0;
}
[email protected]://990487026.blog.51cto.com~/c++$ g++  -g -o run main.cpp && ./run 
development	耶鲁	3.1
development	剑桥	4.1
financial	清华	5.1
sale	斯坦福	1.1
sale	麻省理工	2.1
全部遍历结束

development部门人数:2
development	耶鲁	3.1
development	剑桥	4.1
[email protected]://990487026.blog.51cto.com~/c++$

容器共性机制

1)基本数据类型值拷贝,而不是引用

2)默认构造函数值拷贝,而不是引用

容器的值的寓意:

理论提高:所有容器提供的都是值(value)语意,而非引用(reference)语意。容器执行插入元素的操作时,内部实施拷贝动作。所以STL容器内存储的元素必须能够被拷贝(必须提供拷贝构造函数)。

除了queue与stack外,每个容器都提供可返回迭代器的函数,运用返回的迭代器就可以访问元素。

通常STL不会丢出异常。要求使用者确保传入正确的参数。

每个容器都提供了一个默认构造函数跟一个默认拷贝构造函数。

如已有容器vecIntA。

vector<int> vecIntB(vecIntA); //调用拷贝构造函数,复制vecIntA到vecIntB中。

与大小相关的操作方法(c代表容器):

c.size();   //返回容器中元素的个数

c.empty();   //判断容器是否为空

比较操作(c1,c2代表容器):

c1 == c2     判断c1是否等于c2

c1 != c2      判断c1是否不等于c2

c1 = c2        把c2的所有元素指派给c1

把对象放到容器中,会自动执行拷贝构造函数

[email protected]://990487026.blog.51cto.com~/c++$ cat main.cpp 
#include <iostream>
#include <string.h>
using namespace std;
#include <vector> 

class Teacher
{
public:
	Teacher(const char *name,int age)
	{
		cout << "执行构造函数\n";
		m_name = new char [strlen(name) + 1];
		strcpy(m_name,name);
		m_age = age;
	}
	Teacher(const Teacher &obj)
	{
		cout << "执行拷贝构造函数\n";
		m_name = new char[strlen(obj.m_name) +1];
		strcpy(m_name,obj.m_name);
		m_age = obj.m_age;
	}
	~Teacher()
	{
		if(m_name != NULL)
		{
			cout << "执行析构函数 name=" << m_name << endl;
			delete [] m_name;
			m_name = NULL;
			m_age = 0;
		}
	}
	//重载=号操作符
	Teacher & operator=(const Teacher &obj)
	{
		if(m_name != NULL)
		{
			delete [] m_name;
			m_name = NULL;
			m_age = 0;
		}
		m_name = new char[strlen(obj.m_name) +1];
                strcpy(m_name,obj.m_name);
                m_age = obj.m_age;
		return *this;
	}

public:
	char *m_name;
	int m_age;
};

int main()
{
	Teacher t1("Linux",32);

	vector<Teacher> v1;
	v1.push_back(t1);	//会调用拷贝构造函数,深拷贝,浅拷贝问题

	return 0;
}
[email protected]://990487026.blog.51cto.com~/c++$ g++  -g -o run main.cpp && ./run 
执行构造函数
执行拷贝构造函数
执行析构函数 name=Linux
执行析构函数 name=Linux
[email protected]://990487026.blog.51cto.com~/c++$

各个容器的使用时机

Vector的使用场景:比如软件历史操作记录的存储,我们经常要查看历史记录,比如上一次的记录,上上次的记录,但却不会去删除记录,因为记录是事实的描述。

deque的使用场景:比如排队购票系统,对排队者的存储可以采用deque,支持头端的快速移除,尾端的快速添加。如果采用vector,则头端移除时,会移动大量的数据,速度慢。

list的使用场景:比如公交车乘客的存储,随时可能有乘客下车,支持频繁的不确实位置元素的移除插入。

set的使用场景:比如对手机游戏的个人得分记录的存储,存储要求从高分到低分的顺序排列。

map的使用场景:比如按ID号存储十万个用户,想要快速要通过ID查找对应的用户。二叉树的查找效率,这时就体现出来了。如果是vector容器,最坏的情况下可能要遍历完整个容器才能找到该用户。

vector与deque的比较

一:vector.at()比deque.at()效率高,比如vector.at(0)是固定的,deque的开始位置却是不固定的。

二:如果有大量释放操作的话,vector花的时间更少,这跟二者的内部实现有关。

三:deque支持头部的快速插入与快速移除,这是deque的优点。

---------------------------------------------------------------------------------------------------------------------------





STL算法

1,算法基础:

函数对象

是不是很像函数调用啊,所以又叫做仿函数

[email protected]://990487026.blog.51cto.com~/c++$ cat main.cpp 
#include <iostream>
#include <string.h>
using namespace std;
#include <string> 
#include <vector> 
#include <list> 
#include <set> 
#include <algorithm> 
#include <functional> 

//函数对象 -- 仿函数
template <typename T>
class ShowElemt
{
public:
	void operator()(T &t)
	{
		cout <<t <<endl;
	}
};
int main()
{
	int a = 10;
	ShowElemt<int> showElemt;
	showElemt(a);

	return 0;
}
[email protected]://990487026.blog.51cto.com~/c++$ g++  -g -o run main.cpp && ./run 
10
[email protected]://990487026.blog.51cto.com~/c++$

函数对象 与普通函数的区别: 1,相同之处

[email protected]://990487026.blog.51cto.com~/c++$ cat main.cpp 
#include <iostream>
#include <string.h>
using namespace std;
#include <string> 
#include <vector> 
#include <list> 
#include <set> 
#include <algorithm> 
#include <functional> 

//函数对象 -- 仿函数
template <typename T>
class ShowElemt
{
public:
	void operator()(T &t)//重载括号,使用起来更像函数
	{
		cout <<t <<endl;
	}
};

//函数模板
template <typename T>
void FunShowElemt(T &t)
{
	cout << t << endl;
}

//普通函数
void FunShowElemt(int &t)
{
        cout << t << endl;
}

int main()
{
	int a = 10;
	ShowElemt<int> showElemt;
	showElemt(a);		//函数对象的执行,很像一个函数---仿函数
	FunShowElemt<int>(a);	//函数模板
	FunShowElemt(a);	//普通函数的调用

	return 0;
}

[email protected]://990487026.blog.51cto.com~/c++$ g++  -g -o run main.cpp && ./run 
10
10
10
[email protected]://990487026.blog.51cto.com~/c++$

不同之处

for_each 算法

分清楚STL算法返回值,是迭代器还是函数对象,是STL算法入门的标志

[email protected]://990487026.blog.51cto.com~/c++$ cat main.cpp 
#include <iostream>
#include <string.h>
using namespace std;
#include <string> 
#include <vector> 
#include <list> 
#include <set> 
#include <algorithm> 
#include <functional> 

//函数对象 -- 仿函数
template <typename T>
class ShowElemt
{
public:
	ShowElemt()
	{
		n = 0;
	}
	void operator()(T &t) //重载括号,使用起来更像函数
	{
		n++;	//记录函数运行次数
		cout <<t<< endl;
	}
	void print()
	{
		cout << "函数对象的运行次数为"<<  n << endl;
	}
private:
	int n;
};

//函数模板
template <typename T>
void FunShowElemt(T &t)
{
	cout << t << endl;
}

//普通函数
void FunShowElemt2(int &t)
{
        cout << t << endl;
}

int main()
{
//	int a = 10;
//	ShowElemt<int> showElemt;
//	showElemt(a);		//函数对象的执行,很像一个函数---仿函数
//	FunShowElemt<int>(a);	//函数模板
//	FunShowElemt(a);	//普通函数的调用

	vector<int> v1;
	v1.push_back(1);
	v1.push_back(3);
	v1.push_back(5);
	//遍历容器
	for_each(v1.begin(),v1.end(),ShowElemt<int>() );	//匿名的函数对象
	cout << endl;

	//普通函数做回调函数
	for_each(v1.begin(),v1.end(),FunShowElemt2 );
	cout << endl;

	//函数对象做函数参数
	ShowElemt<int> show1;
	//for_each(v1.begin(),v1.end(),show1);
	show1 = for_each(v1.begin(),v1.end(),show1);
	//for_each算法是值传递,不是引用传递
	//所以在for_each算法内部的数据 与外界不发生任何关系,导致函数对象的数值与外界不关联
	//用函数对象 接 for_each的返回值

	show1.print();

	return 0;
}

[email protected]://990487026.blog.51cto.com~/c++$ g++  -g -o run main.cpp && ./run 
1
3
5

1
3
5

1
3
5
函数对象的运行次数为3
[email protected]://990487026.blog.51cto.com~/c++$

一元谓词函数 案例,查找能够4整除的数

find_if返回的是一个迭代器

[email protected]://990487026.blog.51cto.com~/c++$ cat main.cpp 
#include <iostream>
#include <string.h>
using namespace std;
#include <string> 
#include <vector> 
#include <list> 
#include <set> 
#include <algorithm> 
#include <functional> 

//函数对象  -- 仿函数
template <typename T>
class Isdiv
{
public:
	Isdiv(const T &divisor)
	{
		this->divisor = divisor;
	}
	bool operator()(T &t)
	{
		return (t%divisor == 0);
	}
private:
	T divisor;
};

int main()
{
	vector<int> v1;
	for(int i =9;i<33;i++)
	{
		v1.push_back(i);	//从9开始压入容器
	}

	int a =4;
	Isdiv<int> myDiv(4);

	//方法1
	find_if(v1.begin(),v1.end(),myDiv);

	//方法2
	vector<int>::iterator it;	//因为返回的是一个迭代器
	it = find_if(v1.begin(),v1.end(),Isdiv<int>(a));
	if(it == v1.end())
	{
		cout << "容器中没有能被4整除的元素\n";
	}
	else
	{
		cout << "第一个能被4整除的元素是" << *it << endl;
	}

	return 0;
}

[email protected]://990487026.blog.51cto.com~/c++$ g++  -g -o run main.cpp && ./run 
第一个能被4整除的元素是12
[email protected]://990487026.blog.51cto.com~/c++$

二元对象,二元谓词 案例

[email protected]://990487026.blog.51cto.com~/c++$ cat main.cpp 
#include <iostream>
#include <string.h>
using namespace std;
#include <string> 
#include <vector> 
#include <list> 
#include <set> 
#include <algorithm> 
#include <functional> 

//函数对象  -- 仿函数
template <typename T>
class Sumadd
{
public:
	T operator()(T t1, T t2)
	{
		return t1 + t2;
	}
};

int main()
{
	vector<int> v1;
	vector<int> v2;
	vector<int> v3;
	v1.push_back(1);
	v1.push_back(2);
	v1.push_back(3);

	v2.push_back(4);
	v2.push_back(5);
	v2.push_back(6);

	v3.resize(v1.size());
	transform(v1.begin(),v1.end(),v2.begin(),v3.begin(),Sumadd<int>() );
	for(vector<int>::iterator it=v3.begin();it != v3.end();it++)
	{
		cout << *it << endl;
	}

	return 0;
}
[email protected]://990487026.blog.51cto.com~/c++$ g++  -g -o run main.cpp && ./run 
5
7
9
[email protected]://990487026.blog.51cto.com~/c++$

二元函数  二元谓词的应用

[email protected]://990487026.blog.51cto.com~/c++$ 
[email protected]://990487026.blog.51cto.com~/c++$ cat main.cpp 
#include <iostream>
#include <string.h>
using namespace std;
#include <string> 
#include <vector> 
#include <list> 
#include <set> 
#include <algorithm> 
#include <functional> 

//二元函数  二元谓词
void show(int &t)
{
	cout << t << "  ";
}

bool compare(const int &a,const int &b)
{
	return  a < b;
}

int main()
{
	vector<int> v1(10);
	//遍历
	for(int i=0;i<10;i++)
	{
		int tmp = rand()%100;
		v1[i] = tmp;
	}
	for(vector<int>::iterator it=v1.begin();it!=v1.end();it++)
	{
		cout << *it << "  ";
	}
	cout << endl;

	//排序
	sort(v1.begin(),v1.end(),compare);
	//遍历
	for_each(v1.begin(),v1.end(),show);
	cout << endl;

	return 0;
}
[email protected]://990487026.blog.51cto.com~/c++$ g++  -g -o run main.cpp && ./run 
83  86  77  15  93  35  86  92  49  21  
15  21  35  49  77  83  86  86  92  93  
[email protected]://990487026.blog.51cto.com~/c++$

二元函数  二元谓词在 集合中的应用

1,find函数默认不支持忽略大小写

[email protected]://990487026.blog.51cto.com~/c++$  cat main.cpp 
#include <iostream>
#include <string.h>
using namespace std;
#include <string> 
#include <vector> 
#include <list> 
#include <set> 
#include <algorithm> 
#include <functional> 

int main()
{
	set<string> set1;
	set1.insert("aaa");
	set1.insert("bbb");
	set1.insert("ccc");

	set<string>::iterator it  = set1.find("aaa");
	if(it == set1.end())
	{
		cout << "没有找到 \n";
	}
	else
	{
		cout << "找到了\n";
	}

	it  = set1.find("aAa");
	if(it == set1.end())
	{
		cout << "没有找到 \n";
	}
	else
	{
		cout << "找到了\n";
	}
	return 0;
}
[email protected]://990487026.blog.51cto.com~/c++$ g++  -g -o run main.cpp && ./run 
找到了
没有找到 
[email protected]://990487026.blog.51cto.com~/c++$

二元函数  二元谓词在 集合中的应用

1,让find函数支持忽略大小写

[email protected]://990487026.blog.51cto.com~/c++$ cat main.cpp 
#include <iostream>
#include <string.h>
using namespace std;
#include <string> 
#include <vector> 
#include <list> 
#include <set> 
#include <algorithm> 
#include <functional> 

//仿函数
struct CompareNoCase
{
	bool operator()(const string &str1,const string &str2)
	{
		//cout << str1 << "\t" << str2 << endl;
		string str1_;
		str1_.resize(str1.size());
		transform(str1.begin(),str1.end(),str1_.begin(),::tolower);	//tolower是STL预定义的

		string str2_;
		str2_.resize(str2.size());
		transform(str2.begin(),str2.end(),str2_.begin(),::tolower);	//tolower是STL预定义的
		//cout << str1_ << "\t" << str2_ << endl;

		return (str1_ < str2_);
	}
};
int main()
{
	set<string> set1;
	set1.insert("aaa");
	set1.insert("bbb");
	set1.insert("ccc");

	set<string>::iterator it  = set1.find("aAa");
	if(it == set1.end())
	{
		cout << "没有找到 \n";
	}
	else
	{
		cout << "找到了\n";
	}
//////////////////////////////////////////////////////////////
	set<string,CompareNoCase> set2;
	set2.insert("aaa");
	set2.insert("bbb");
	set2.insert("ccc");

	set<string,CompareNoCase>::iterator it2  = set2.find("aAa");
	if(it2 == set2.end())
	{
		cout << "没有找到 \n";
	}
	else
	{
		cout << "找到了\n";
	}

	return 0;
}

[email protected]://990487026.blog.51cto.com~/c++$ 
[email protected]://990487026.blog.51cto.com~/c++$ g++  -g -o run main.cpp && ./run 
没有找到 
找到了
[email protected]://990487026.blog.51cto.com~/c++$

预定义函数对象  与 函数适配器

[email protected]://990487026.blog.51cto.com~/c++$ cat main.cpp 
#include <iostream>
#include <string.h>
using namespace std;
#include <string> 
#include <vector> 
#include <list> 
#include <set> 
#include <algorithm> 
#include <functional> 

int main()
{
	//预定义好的函数对象,能实现不同数据类型的运算
	//实现了数据类型 与 算法 的分离
	plus<int> intadd;
	int a = 10;
	int b = 20;
	int c = intadd(a,b);
	cout << c << endl;

	plus<string> stradd;
	string s1 = "Hello ";
	string s2 = "Linux!";
	string s3 = stradd(s1,s2);
	cout << s3 << endl;
	cout << endl;

	vector<string> v1;
	v1.push_back("AAA");
	v1.push_back("BBB");
	v1.push_back("CCC");
	v1.push_back("CCC");
	v1.push_back("CCC");
	sort(v1.begin(),v1.end(),greater<string>() );	//从大到小 排序
	for(vector<string>::iterator it = v1.begin();it!=v1.end();it++)
	{
		cout << *it << " ";
	}
	cout << endl;

	//函数适配器  -- 求CCC出现的次数
	string sc = "CCC";
	//bind2nd 函数适配器,把预定义函数对象 与 第二个函数的参数绑定
	int num = count_if(v1.begin(),v1.end(),bind2nd(equal_to<string>(),sc) );
	cout << num << "\n";

	return 0;
}
/*
	如何知道plus<int> 需要两个参数?
	打开调试	gdb run
	加断点		(gdb) break main.cpp:18
	开始运行 	(gdb) run
	进入函数	(gdb) step
	可以看到	std::plus<int>::operator() (this=0x7fffffffeac2, [email protected]: 10, [email protected]: 20)
			at /usr/include/c++/4.8/bits/stl_function.h:144

*/

[email protected]://990487026.blog.51cto.com~/c++$ g++  -g -o run main.cpp && ./run 
30
Hello Linux!

CCC CCC CCC BBB AAA 
3
[email protected]://990487026.blog.51cto.com~/c++$

函数适配器综合案例 统计大于8的元素个数,预定于与谓词 band2nd 与 not

[email protected]://990487026.blog.51cto.com~/c++$ cat main.cpp 
#include <iostream>
#include <string.h>
using namespace std;
#include <string> 
#include <vector> 
#include <list> 
#include <set> 
#include <algorithm> 
#include <functional> 

struct IsGreat
{
public:
	IsGreat(int i)
	{
		m_num = i;
	}
	bool operator()(int &num)
	{
		return (num > m_num);
	}
private:
	int m_num;
};
int main()
{
	vector<int> v1;
	for(int i = 0;i<10;i++)
	{
		v1.push_back(i+1);
	}
	//遍历
	for(vector<int>::iterator it = v1.begin();it != v1.end();it++)
	{
		cout << *it << " ";
	}
	cout << endl;

	//统计数组容器中元素为3的个数
	int num1 = count(v1.begin(),v1.end(),3);
	cout <<"元素为3的个数有 " <<num1 << endl;

	//通过谓词,统计数组容器中元素大于2的个数
	int num2 = count_if(v1.begin(),v1.end(),IsGreat(8));
	cout <<"元素大于8的个数有 " <<num2 << endl;

	//通过预定义函数,统计数组容器中元素大于2的个数
	//greater<int>需要两个参数,左边来自容器中的每一个,右边的需要绑定
	int num3 = count_if(v1.begin(),v1.end(),bind2nd(greater<int>(),7) );
	cout <<"元素大于7的个数有 " <<num3 << endl;

	//求奇数的个数
	int num4 = count_if(v1.begin(),v1.end(),bind2nd(modulus<int>(),2) );
	cout <<"元素奇数的个数有 " <<num4 << endl;

	//求偶数的个数 ,not1 翻转一元预定义函数的正值
	int num5 = count_if(v1.begin(),v1.end(),not1(bind2nd(modulus<int>(),2)));
	cout <<"元素偶数的个数有 " <<num5 << endl;

	return 0;
}
[email protected]://990487026.blog.51cto.com~/c++$ g++  -g -o run main.cpp && ./run 
1 2 3 4 5 6 7 8 9 10 
元素为3的个数有 1
元素大于8的个数有 2
元素大于7的个数有 3
元素奇数的个数有 5
元素偶数的个数有 5
[email protected]://990487026.blog.51cto.com~/c++$

2,遍历算法:

1 容器的遍历1  迭代器

[email protected]://990487026.blog.51cto.com~/c++$ cat main.cpp 
//STL常用算法

#include <iostream>
#include <string.h>
using namespace std;
#include <string> 
#include <vector> 
#include <list> 
#include <set> 
#include <algorithm> 
#include <functional> 

void print(vector<int> &v)
{
	for(vector<int>::iterator it = v.begin();it != v.end();it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}
int main()
{
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(2);
	v1.push_back(3);
	print(v1);

	return 0;
}
[email protected]://990487026.blog.51cto.com~/c++$ g++  -g -o run main.cpp && ./run 
1 2 3 
[email protected]://990487026.blog.51cto.com~/c++$

2 容器的遍历  自定义函数

[email protected]://990487026.blog.51cto.com~/c++$ cat stl_01.cpp 
//STL常用算法

#include <iostream>
#include <string.h>
using namespace std;
#include <string> 
#include <vector> 
#include <list> 
#include <set> 
#include <algorithm> 
#include <functional>

void show_vector(int n)
{
	cout << n << " ";
}
int main()
{
        vector<int> v1; 
        v1.push_back(1);
        v1.push_back(2);
        v1.push_back(3);
	for_each(v1.begin(),v1.end(),show_vector);//会把左边每一个元素传进来
	cout << endl;

        return 0;
}

[email protected]://990487026.blog.51cto.com~/c++$ g++  -g -o run stl_01.cpp && ./run 
1 2 3 
[email protected]://990487026.blog.51cto.com~/c++$

3 容器的遍历 仿函数

[email protected]://990487026.blog.51cto.com~/c++$ cat stl_02.cpp 
//STL常用算法

#include <iostream>
#include <string.h>
using namespace std;
#include <string> 
#include <vector> 
#include <list> 
#include <set> 
#include <algorithm> 
#include <functional>
class Show_Vector
{
public:
	void operator()(int &n)
	{
		cout << n << " ";
	}
};

int main()
{
        vector<int> v1; 
        v1.push_back(1);
        v1.push_back(2);
        v1.push_back(3);
	for_each(v1.begin(),v1.end(),Show_Vector());//会把左边每一个元素传进来
	cout << endl;

        return 0;
}

[email protected]://990487026.blog.51cto.com~/c++$ g++  -g -o run stl_02.cpp && ./run 
1 2 3 
[email protected]://990487026.blog.51cto.com~/c++$

transform 使用回调函数修改自己的容器

[email protected]://990487026.blog.51cto.com~/c++$ cat stl_03.cpp 
//STL常用算法

#include <iostream>
#include <string.h>
using namespace std;
#include <string> 
#include <vector> 
#include <list> 
#include <set> 
#include <algorithm> 
#include <functional>

void print(vector<int> &v)
{
	for(vector<int>::iterator it = v.begin();it != v.end();it++)
	{
		cout << *it << "\t";
	}
	cout << endl;
}

int increase(int n)
{
	return n + 100;
}

int main()
{
        vector<int> v1; 
        v1.push_back(1);
        v1.push_back(2);
        v1.push_back(3);
        v1.push_back(4);
        v1.push_back(5);
	print(v1);
	transform(v1.begin(),v1.end(),v1.begin(),increase);	//使用了回调函数
	print(v1);

        return 0;
}

[email protected]://990487026.blog.51cto.com~/c++$ g++  -g -o run stl_03.cpp && ./run 
1	2	3	4	5
101	102	103	104	105
[email protected]://990487026.blog.51cto.com~/c++$

transform 使用预定义函数修改自己的容器

[email protected]://990487026.blog.51cto.com~/c++$ cat stl_03.cpp 
//STL常用算法

#include <iostream>
#include <string.h>
using namespace std;
#include <string> 
#include <vector> 
#include <list> 
#include <set> 
#include <algorithm> 
#include <functional>

void print(vector<int> &v)
{
	for(vector<int>::iterator it = v.begin();it != v.end();it++)
	{
		cout << *it << "\t";
	}
	cout << endl;
}

int increase(int n)
{
	return n + 100;
}

int main()
{
        vector<int> v1; 
        v1.push_back(1);
        v1.push_back(2);
        v1.push_back(3);
        v1.push_back(4);
        v1.push_back(5);
	print(v1);
	transform(v1.begin(),v1.end(),v1.begin(),negate<int>());//使用了预定义函数
	print(v1);

        return 0;
}

[email protected]://990487026.blog.51cto.com~/c++$ g++  -g -o run stl_03.cpp && ./run 
1	2	3	4	5
-1	-2	-3	-4	-5
[email protected]://990487026.blog.51cto.com~/c++$

使用函数适配器 与 函数对象:

利用transform ,使用适配器,将计算结果储存到list容器

直接将结果输出到屏幕

[email protected]://990487026.blog.51cto.com~/c++$ cat stl_03.cpp 
//STL常用算法
#include <iostream>
#include <string.h>
using namespace std;
#include <string> 
#include <vector> 
#include <list> 
#include <set> 
#include <algorithm> 
#include <functional>
#include <iterator> //直接将结果输出到屏幕

void print_vector(vector<int> &v)
{
	for(vector<int>::iterator it = v.begin();it != v.end();it++)
	{
		cout << *it << "\t";
	}
	cout << endl;
}

void print_list(list<int> &l)
{
	for(list<int>::iterator it = l.begin();it != l.end();it++)
	{
		cout << *it << "\t";
	}
	cout << endl;
}

int main()
{
        vector<int> v1; 
        v1.push_back(1);
        v1.push_back(2);
        v1.push_back(3);
        v1.push_back(4);
        v1.push_back(5);
	print_vector(v1);

	//利用transform ,使用适配器,将计算结果储存到list容器
	list<int> list1;	//定义一个list int变量
	list1.resize(v1.size());//改变容量
	transform(v1.begin(),v1.end(),list1.begin(),bind2nd(multiplies<int>(),10));
	print_list(list1);	//运算结果已经存储到list1

	//直接将结果输出到屏幕
	transform(v1.begin(),v1.end(),ostream_iterator<int>(cout,"\t"),negate<int>());
	cout << endl;
        return 0;
}

[email protected]://990487026.blog.51cto.com~/c++$ g++  -g -o run stl_03.cpp && ./run 
1	2	3	4	5
10	20	30	40	50
-1	-2	-3	-4	-5
[email protected]://990487026.blog.51cto.com~/c++$

transform 与 for_each比较

[email protected]://990487026.blog.51cto.com~/c++$ cat stl_03.cpp 
//STL常用算法
#include <iostream>
#include <string.h>
using namespace std;
#include <string> 
#include <vector> 
#include <list> 
#include <set> 
#include <algorithm> 
#include <functional>
#include <iterator>

void Show_Vector(int &n)
{
	cout << n << "\t";
}

int print_vector(int n)
{
	cout << n<< "\t";
	return n;
}

int main()
{
        vector<int> v1; 
        v1.push_back(1);
        v1.push_back(3);
        v1.push_back(5);
	for_each(v1.begin(),v1.end(),Show_Vector);
	cout << endl;

	transform(v1.begin(),v1.end(),v1.begin(),print_vector);
	cout << endl;
        return 0;
}

/*
1) for+each对函数对象的要求:for_each函数原型:
	template<class _InIt,
	class _Fn1> inline
		_Fn1 for_each(_InIt _First, _InIt _Last, _Fn1 _Func)
	{	// perform function for each element
		_DEBUG_RANGE(_First, _Last);
		_DEBUG_POINTER(_Func);

2) transform 对 函数对象的要求,transform函数原型:
	template<class _InIt,
	class _OutIt,
	class _Fn1> inline
		_OutIt _Transform(_InIt _First, _InIt _Last,
		_OutIt _Dest, _Fn1 _Func)
	{	// transform [_First, _Last) with _Func
		for (; _First != _Last; ++_First, ++_Dest)
			*_Dest = _Func(*_First);  //解释了 为什么 要有返回值
		return (_Dest);
	}
*/
//一般情况下:for_each所使用的函数对象,参数是引用,没有返回值
//transform所使用的函数对象,参数一般不使用引用,而是还有返回值

[email protected]://990487026.blog.51cto.com~/c++$ g++  -g -o run stl_03.cpp && ./run 
1	3	5
1	3	5
[email protected]://990487026.blog.51cto.com~/c++$
时间: 2024-10-17 21:16:19

c++ 提高4 map容器 共性机制 使用时机 比较| STL算法 算法基础仿函数 谓词 函数适配器 遍历算法的相关文章

STL容器共性机制和使用场景

一.STL容器共性机制 STL容器所提供的都是值(value)寓意,而非引用(reference)寓意,也就是说当我们给容器中插入元素的时候,容器内部实施了拷贝动作,将我们要插入的元素再另行拷贝一份放入到容器中,而不是将原数据元素直接放进容器中,也就是说我们提供的元素必须能够被拷贝. 除了queue和stack之外,每个容器都提供可返回迭代器的函数,运用返回的迭代器就可以访问元素. 通过STL不会抛出异常,需要使用者传入正确参数. 每个容器都提供一个默认的构造函数和默认的拷贝构造函数. 大小相关

hdu 4941 Magical Forest (map容器)

Magical Forest Time Limit: 24000/12000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 135    Accepted Submission(s): 69 Problem Description There is a forest can be seen as N * M grid. In this forest, there is so

HDU 1113 Word Amalgamation (map 容器 + string容器)

http://acm.hdu.edu.cn/showproblem.php?pid=1113 Problem Description In millions of newspapers across the United States there is a word game called Jumble. The object of this game is to solve a riddle, but in order to find the letters that appear in th

简单即用的临时Map容器(参考TimeCacheMap和RotatingMap)

因为业务需要,经常会缓存一些临时数据.比如:手机号发送验证码, 60s内同一个手机号不能重复发送验证码.查询航班信息,缓存1分钟热门查询数据.... 之前一直使用redis作为数据缓存,简单方便..但是如果是个小App,数据没有那么大,可能需要缓存的数据只有不到100KB,使用redis就大材小用 最近一个项目上线的时候,老大跟我说:真的有必要用redis么..不行就先删掉吧..自己想了下,因为App入口有两个ip,不同机器,虽然业务量不大,为了session共享,还是上了 如果只有一个入口(不

【转】C++中map容器的说明和使用技巧

C++中map容器提供一个键值对容器,map与multimap差别仅仅在于multiple允许一个键对应多个值. 一.map的说明    1   头文件   #include   <map>     2   定义   map<string,   int>   my_Map;   或者是typedef     map<string,   int>   MY_MAP;   MY_MAP   my_Map;     3   插入数据   (1)   my_Map["

HNU 12888 Encryption(map容器)

题目链接:http://acm.hnu.cn/online/?action=problem&type=show&id=12890&courseid=274 解题报告:输入一个有n个单词的句子,然后再输入这n个单词对应的意思是什么,要你翻译出这个句子最后是什么. 一个裸的map 1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm>

set和map容器、

set集合容器:实现了红黑树的平衡二叉检索树的数据结构,插入元素时,它会自动调整二叉树的排列,把元素放到适当的位置,以保证每个子树根节点键值大于左子树所有节点的键值,小于右子树所有节点的键值:另外,还得保证根节点左子树的高度与右子树高度相等. 平衡二叉检索树使用中序遍历算法,检索效率高于vector.deque和list等容器,另外使用中序遍历可将键值按照从小到大遍历出来. 构造set集合主要目的是为了快速检索,不可直接去修改键值.要注意的是,它不会重复插入相同的键值,而采取忽略处理. set集

c++ STL map容器成员函数

map容器用于查找,设置键值和元素值,输入键值,就能得到元素值.map对象中的元素时刻都是有序的,除非无序插入的.它是用平衡树创建的.查找很快. 函数 描述,注意有r的地方都是不能用it代替的. map (comp,alloc) map (it first, it last, comp,alloc) map (map& x) Comp为比较函数,用于排序,alloc不用鸟它.两个参数有默认值,可不填,按默认的.创建空map. 用一段元素填充,并设置排序函数. 拷贝x中的元素并创建新map.估计新

关于map 容器insert顺序

今天测试我的节点,maya一次次死掉,一点一点的打印测试,良久才知:我想当然的将插入map的顺序,作为我执行的顺序直接遍历,打印数据显示,map有自动将键值排序的功能,比如以字符串为例,会按照a.b.c....顺序排好. 而且对于map,如果一个元素key不存在,但是直接map[key],那么map的size就增加1,我感觉有点儿相当于insert,但map[key]没有值.这样很不规范,对于有一定代码量的程序测试造成不必要的困扰,所以最好使用find函数,判断是否==map.end() 关于s