码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2016-07-20 15:09:14      阅读:330      评论:0      收藏:0      [点我收藏+]

标签: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中初始化 遍历

chunli@http://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;
}
chunli@http://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
chunli@http://990487026.blog.51cto.com~/c++$




map容器 元素的删除

chunli@http://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;
}
chunli@http://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
chunli@http://990487026.blog.51cto.com~/c++$




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

chunli@http://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;
}
chunli@http://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
chunli@http://990487026.blog.51cto.com~/c++$




map的查找,异常处理

chunli@http://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;
}
chunli@http://990487026.blog.51cto.com~/c++$ g++  -g -o run main.cpp && ./run 
7	VIM
没有找到
chunli@http://990487026.blog.51cto.com~/c++$



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

chunli@http://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;
}
chunli@http://990487026.blog.51cto.com~/c++$ g++  -g -o run main.cpp && ./run 
7	VIM
8	tcpdump
chunli@http://990487026.blog.51cto.com~/c++$


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

chunli@http://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;
}
chunli@http://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
chunli@http://990487026.blog.51cto.com~/c++$



容器共性机制

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

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


容器的值的寓意:

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

 

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

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

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

  如已有容器vecIntA

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

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

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

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

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

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

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

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



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

chunli@http://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;
}
chunli@http://990487026.blog.51cto.com~/c++$ g++  -g -o run main.cpp && ./run 
执行构造函数
执行拷贝构造函数
执行析构函数 name=Linux
执行析构函数 name=Linux
chunli@http://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,算法基础:


    函数对象

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

chunli@http://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;
}
chunli@http://990487026.blog.51cto.com~/c++$ g++  -g -o run main.cpp && ./run 
10
chunli@http://990487026.blog.51cto.com~/c++$




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

chunli@http://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;
}

chunli@http://990487026.blog.51cto.com~/c++$ g++  -g -o run main.cpp && ./run 
10
10
10
chunli@http://990487026.blog.51cto.com~/c++$



不同之处

for_each 算法

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

chunli@http://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;
}





chunli@http://990487026.blog.51cto.com~/c++$ g++  -g -o run main.cpp && ./run 
1
3
5

1
3
5

1
3
5
函数对象的运行次数为3
chunli@http://990487026.blog.51cto.com~/c++$


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

find_if返回的是一个迭代器

chunli@http://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;
}





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


二元对象,二元谓词 案例

chunli@http://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;
}
chunli@http://990487026.blog.51cto.com~/c++$ g++  -g -o run main.cpp && ./run 
5
7
9
chunli@http://990487026.blog.51cto.com~/c++$


二元函数  二元谓词的应用

chunli@http://990487026.blog.51cto.com~/c++$ 
chunli@http://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;
}
chunli@http://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  
chunli@http://990487026.blog.51cto.com~/c++$




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

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

chunli@http://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;
}
chunli@http://990487026.blog.51cto.com~/c++$ g++  -g -o run main.cpp && ./run 
找到了
没有找到 
chunli@http://990487026.blog.51cto.com~/c++$


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

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

chunli@http://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;
}



chunli@http://990487026.blog.51cto.com~/c++$ 
chunli@http://990487026.blog.51cto.com~/c++$ g++  -g -o run main.cpp && ./run 
没有找到 
找到了
chunli@http://990487026.blog.51cto.com~/c++$




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

chunli@http://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, __x=@0x7fffffffeac4: 10, __y=@0x7fffffffeac8: 20)
			at /usr/include/c++/4.8/bits/stl_function.h:144
	

	
*/




chunli@http://990487026.blog.51cto.com~/c++$ g++  -g -o run main.cpp && ./run 
30
Hello Linux!

CCC CCC CCC BBB AAA 
3
chunli@http://990487026.blog.51cto.com~/c++$






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

chunli@http://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;
}
chunli@http://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
chunli@http://990487026.blog.51cto.com~/c++$





2,遍历算法:

1 容器的遍历1  迭代器

chunli@http://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;
}
chunli@http://990487026.blog.51cto.com~/c++$ g++  -g -o run main.cpp && ./run 
1 2 3 
chunli@http://990487026.blog.51cto.com~/c++$


2 容器的遍历  自定义函数

chunli@http://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;
}

chunli@http://990487026.blog.51cto.com~/c++$ g++  -g -o run stl_01.cpp && ./run 
1 2 3 
chunli@http://990487026.blog.51cto.com~/c++$



3 容器的遍历 仿函数

chunli@http://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;
}


chunli@http://990487026.blog.51cto.com~/c++$ g++  -g -o run stl_02.cpp && ./run 
1 2 3 
chunli@http://990487026.blog.51cto.com~/c++$



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

chunli@http://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;
}


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


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

chunli@http://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;
}


chunli@http://990487026.blog.51cto.com~/c++$ g++  -g -o run stl_03.cpp && ./run 
1	2	3	4	5	
-1	-2	-3	-4	-5	
chunli@http://990487026.blog.51cto.com~/c++$



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

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

直接将结果输出到屏幕

chunli@http://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;
}


chunli@http://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	
chunli@http://990487026.blog.51cto.com~/c++$



transform 与 for_each比较

chunli@http://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所使用的函数对象,参数一般不使用引用,而是还有返回值

chunli@http://990487026.blog.51cto.com~/c++$ g++  -g -o run stl_03.cpp && ./run 
1	3	5	
1	3	5	
chunli@http://990487026.blog.51cto.com~/c++$








本文出自 “魂斗罗” 博客,谢绝转载!

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

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

原文地址:http://990487026.blog.51cto.com/10133282/1828046

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!