《21天学通C++》[美] —全文笔记(中) 潦草版

第13 章 标准模板库STL

  13.1 标准模板库简介

        1、STL容器

        容器是存储数据的STL类,STL提供顺序容器、关联容器

        顺序容器:例如vector、deque、list、forward_list等,按顺序存储,插入元素快速,查找元素相对较慢。

        关联容器:例如set、map、multiset、multimap等,按指定顺序存储,像字典一样,插入元素较慢,查询快速。

        容器适配器:例如栈stack、队列queue,是顺序容器和关联容器的变种,功能进行限制满足特定需求。

        2、STL迭代器:最简单的迭代器是指针,可将迭代器视为泛型指针,是容器和算法的桥梁。

        3、STL算法:例如find、reverse、transform等,算法结合迭代器对容器中的数据进行操作。

  13.2 STL string类

1、实例化和复制string对象
	const char* str = "Hello World";	//常量字符串
	string str1(str);			//1、初始化
	string str2 = str;			//2、赋值
	string str3("Hello World"); //3、初始化
	string str4(str3);			//4、使用string对象初始化
	string str5(str, 5);		//5、使用str字符串前5个初始化
	string str6(10, 'A');		//6、使用10个A字符初始化
    string::const_iterator p;   //7、声明一个指向string元素的迭代器(改为iterator,迭代器可修改)
2、访问string的内容
	string str("Hello String");
	//数组[]访问方式:
	for (int i = 0; i < str.length(); i++)	//str.length()返回字符串长度
	{
		cout << str[i] << endl;				
	}
	int i=0;
	//迭代器方式:
	for (string::const_iterator p = str.begin(); p < str.end(); ++p)
	{
		cout << *p << endl;					
	}
3、拼接字符串
	string str1("Hello ");
	string str2("String");
	str1 += str2;		//1、运算符+=
	str1.append(str2);	//2、成员函数append()
	str1.append("String");
4、查找字符或字符串
	string str("Hello String");
	int flag = str.find("Str", 0);//从0位置起始查找,//成功返回位置,失败返回npos(-1)
	if (flag != string::npos)
		cout << "YES"<< endl;
	else cout << "NO" << endl;
5、截短string
	string str("Hello String");
	str.erase(5, 1);//1、起始位置 + 数量(一段)
	str.erase(2);	//2、起始位置到结束(一段)
	//此处string::iterator类型 应使用auto进行简化
	string::iterator pos = std::find(str.begin(), str.end(),'t');
                                    //(算法std::find()),查找字符位置
	if (pos != str.end())
		str.erase(pos);	//3、位置(一点)
	str.erase(str.begin(), str.end());//4、删除由两个迭代器指定的范围,此处为字符串起始到结束
6、字符串反转(算法std::reverse())
    #include<algorithm>
	string str("Hello String");
	reverse(str.begin(), str.end());//将字符串str进行反转
7、字符串大小写转换
	string str("Hello String");
	//(输入起始迭代器,输入结束,输出起始,转换格式),对范围内的每个字符调用toupper()函数
	transform(str.begin(), str.end(), str.begin(), ::toupper);//大写
	transform(str.begin(), str.end(), str.begin(), ::tolower);//小写
8、基于模板的string实现
	//容器类basic_string模板:
    template<class _Elem,class _Traits,class _Alloc>//_Elem参数将指定对象存储的数据类型
    class basic_string{
    };
	//basic_string具体化string:
    typedef basic_string<char, char_traits<char>, allocator<char>> string;
9、C++14 ""s
    string str("hello \0 world");//字符串常量中的\0将终止
	string str2("hello \0 world"s);//包含\0

  13.3 动态数组类vector与deque

1、实例化vector
    #include<vector>
	std::vector<int> a;						//int类型
	std::vector<int> b{ 1, 2, 3, 4, -1 };	//int类型,列表初始化
	vector<float> c(10);					//float类型,10个元素
	vector<int> d(10, 100);					//10个元素,每个元素初始值为100
	vector<int> e(d);						//使用vector初始化
	vector<int> f(d.begin(), d.begin() + 5);//使用迭代器初始化,指定范围
    vector<int>::const_iterator p;          //声明一个指向vector中元素的迭代器(iterator,则迭代器可修改)
2、尾插push_back()
    std::vector<int> a;
	a.push_back(10);		//在末尾插入一个元素,值为10
3、指定位置插入insert()
	std::vector<int> a;
	vector<int>b = { 1, 2, 3, 4, 5 };
	a.push_back(10);				//1、在末尾插入一个元素,值为10
	a.insert(a.begin(), 25);		//2、在指定位置插入指定值
	a.insert(a.begin(), 10, 99);	//3、位置,数量,值
	a.insert(a.begin() + 1, b.begin(), b.end());//4、将另一个vector插入指定位置
	for (int i = 0; i < a.size();i++)
		cout << a[i] << endl;
4、访问数组元素
    vector<int>num = { 1, 2, 3 };
	num[0] = 10;			//使用数组[]方式访问元素
	vector<int>::const_iterator p = num.begin();//使用迭代器(类似指针)访问vector元素
	cout << *(p+1) << endl;
5、删除末尾元素pop_back()
	vector<int>num = { 1, 2, 3 };
	num.pop_back();
6、大小与容量
	//size()返回元素数量,capacity()返回容量大小
	vector<int>num = { 1, 2,3};
	num.push_back(1);//插入元素
	cout << num.size() << num.capacity() << endl;//4,4
	num.push_back(1);//插入元素
	cout << num.size() << num.capacity() << endl;//5,6
	//在插入操作改变大小时,容量会多增大一些,避免频繁扩容
    num.reserve(10);//改变容量大小,设置容量
7、deque类
    deque与vector不同点:deque可以使用push_front和pop_front在开头插入删除元素
	#include<deque>
	deque<int>num = { 1, 2, 3 };
	num.push_front(10); //在头部 插入元素
	num.pop_front();	//在头部 删除元素

  13.4 STL list(链表)和forward_list

1、实例化list对象
    #include<list>    //头文件
	std::list<int>link1;		//1、int类型
	list<float>link2;			//2、float类型
	list<int>link3(10);			//3、10个元素
	list<int>link4(10, 99);		//4、10个元素,初始值99
	list<int>link5(link4);		//5、用另一个list初始化
	vector<int> a(10, 99);
	list<int>link6(a.begin(), a.end());	//6、用vector对象值进行初始化list
	list<int>::const_iterator p;//7、声明一个指向list中元素的迭代器
	for (list<int>::const_iterator i = link6.begin(); i != link6.end(); ++i)
		cout << *i << endl;		//8、访问link6

2、头部或尾部插入push_front()或push_back()
	list<int>link{ 1, 2, 3 };//列表初始化
	link.push_front(0);	//头插
	link.push_back(4);	//尾插
	for (auto i = link.begin(); i != link.end(); ++i)
		cout << *i << endl;//打印

3、中间插入insert()
	list<int>link{ 1, 2, 3 };//列表初始化
	link.insert(link.begin(), 0);//1、位置,值
	link.insert(link.end(), 4);
	link.insert(link.begin(), 4, 0);//2、位置,数量,值
	list<int>link1{ 9, 9, 9 };
	link.insert(link.begin(), link1.begin(), link1.end());//3、位置,(位置,位置)另一对象的迭代器
4、删除元素erase()
	list<int>link{ 1, 2, 3 };
	link.erase(link.begin());				//1、删除迭代器指向的元素
	link.erase(link.begin(), link.end());	//2、删除迭代器区间的所有元素
    link.clear();                           //3、清空容器
5、反转元素reverse()
    list<int>link{ 1, 2, 3 };
	link.reverse();
6、元素排序sort()
    bool sort_func(const int& a, const int& b)
    {
    	return (a > b);	
    }
    list<int>link{ 4, 1, 5, 2, 3, 7, 10};
	link.sort();	//默认从小到大
	for (auto i = link.begin(); i != link.end(); ++i)
		cout << *i << endl;//打印
	link.sort(sort_func);//从大到小(参数为一个二元谓词)

7、forward_list单向链表
    #include<forward_list>
	forward_list<int> link{ 1,2, 3, 5, 2, 4, 6 };//1、初始化
	link.push_front(9);			//2、只能头插
	link.remove(2);				//3、删除值为2的所有元素
	link.sort();				//4、从小到大排序

  13.5 STL set和multiset

        容器在插入元素时自动进行排序,

1、实例化set与multiset
	//set与multiset区别:后者可存储重复的值
    #include<set>
	set<int> num1;          //1、声明int类型
	multiset<int> num2;
	set<int> num3(num1);    //2、用另一set进行初始化
	set<int>::const_iterator      p1;   //3、声明指向set或multiset中元素的迭代器
	multiset<int>::const_iterator p2;

2、插入元素insert
    set<int> num1{1,3,5,7,2,4,6,8};//1、声明int类型
	multiset<int> num2;
	num2.insert(3);//1、插入值3的元素(multiset可接受重复的值)
	num2.insert(num1.begin(), num1.end());//2、插入迭代器范围的值
	num2.count(3);//3、返回值为3的元素的数量
3、查找元素find
    set<int> num{1,3,5,7,2,4,6,8};//1、声明int类型
	set<int>::const_iterator p = num.find(1);//find查找值为1的元素,返回迭代器
	if (p != num.end())//将返回的迭代器与end比较,判断是否找到指定的元素
		cout << *p;
	//multiset存在重复的值,因此返回查找到的第一个迭代器
4、删除erase
    set<int> num{1,3,5,7,2,4,6,8};
	num.erase(3);			//1、删除值为3的元素
	num.erase(num.find(6)); //2、删除迭代器指向的元素
	num.erase(num.find(5), num.end());//3、删除迭代器范围内的所有元素
5、散列表

  13.6 STL map和multimap

        容器在插入元素时按照键,自动进行排序(数据形式为:键 值对)

1、实例化map和multimap(multimap可存储重复键)
    #include<map>
    template<typename T>
    struct reversesort
    {
    	bool operator()(const T& key1, const T& key2)
    	{
	    	return (key1 > key2);
	    }
    };
    map<int, string>map1;
	multimap<int, string>map2;		//1、键类型int,值类型string
	map<int, string>map3(map1);		//2、用另一map初始化
	map<int, string>map4(map1.begin(), map1.end());//3、使用另一map的两个迭代器初始化
	map<int, string, reversesort<int>> map4(map1.begin(), map1.end());
									//4、reversesort<int>为自定义排序,默认升序排序
2、插入insert
    map<int, string> num;
	num.insert(map<int,string>::value_type(3,"Three")); //1、
	num.insert(make_pair(-1, "Minus One"));			    //2、
	num.insert(pair<int, string>(1000, "One Thousand"));//3、
	num[10000] = "One Million";							//4、
	cout << num.size() << endl;
	for (auto i = num.begin(); i != num.end(); ++i)		//键值按默认排序(由小到大)输出
		cout << i->first << " , " << i->second << endl; //键:first 值:second
3、查找find
    map<int, string> num1;
	multimap<int, string>num2;
	auto p1 = num1.find(10);//查找键为10的键值对,返回迭代器
	auto p2 = num2.find(10);//同一个键可能存在多个键值对,需要再进行查找
	size_t n = num2.count(10);//返回键为10的键值对数量
4、删除erase
	multimap<int, string>num;
	num.insert(make_pair(3, "Three"));
	num.insert(make_pair(5, "Five"));
	num.insert(make_pair(100, "Five"));
	num.insert(make_pair(1000, "Five"));
	auto p1 = num.erase(3);//1、删除键为3的键值对,返回值为删除的键值对数量
	auto p2 = num.find(5);
	auto p3 = num.erase(p2);//2、使用迭代器作为参数删除
	num.erase(num.lower_bound(100), num.upper_bound(1000));//3、使用迭代器指定边界,删除范围
5、散列表

第14 章 函数对象与lambda表达式

  14.1 函数对象

        函数对象是实现了operator()的类的对象,在结构体或类中实现函数对象时,比简单函数有用,可以使用数据成员存储与状体相关的信息,谓词可以用于做决策的算法。

        一元函数:接收一个参数,(如果返回一个布尔值,称为一元谓词)

        二元函数:接收两个参数,(如果返回一个布尔值,称为二元谓词)

  14.2 一元函数

    template<typename T>
    void func(const T& element)	//1、一元函数
    {
    	cout << element << ' ';
    }
    template<typename T>
    struct function				//2、作为类或结构的operator()
    {
    	void operator()(const T& element)const
    	{
    		cout << element << ' ';
    	}
    };
	vector<int>num{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	for_each(num.begin(), num.end(), func<int>);//STL算法,显示集合的内容,每次显示一个元素
                        //for_each()函数对每个元素,调用function::operator()进行打印操作
	for_each(num.begin(), num.end(), function<int>());

  14.3 可保存状态的函数对象

    template<typename T>
    struct function				
    {
    	int count;				
    	function() :count(0){}	//构造函数
    	void operator()(const T& element)
    	{
    		++count;	//计数
    		cout << element << ' ';
    	}
    };
	vector<int>num{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	function<int> n;
	n = for_each(num.begin(), num.end(), function<int>());
	cout <<endl<< n.count << endl;

  14.4 一元谓词

    template<typename T>
    struct function				
    {
    	T count;
    	function(const T& n):count(n){}	//构造函数
    	bool operator()(const T& element)const//返回布尔值
    	{
    		return((element%count) == 0);//判断整除
    	}
    };
	vector<int>num{  1, 2, 3, 4, 6, 7, 8, 9 ,10};
	auto n = find_if(num.begin(), num.end(), function<int>(5));
			//find_if对每个元素调用function::operator(),返回第一个被整除的元素的迭代器
            //operator()返回true时,find_if()返回迭代器
	cout << *n << endl;

  14.5 二元函数

    template<typename T>
    class function		//在类中实现		
    {
    public:
    	T operator()(const T& element1,const T& element2)
    	{
    		return(element1*element2);//返回乘法结果
    	}
    };
	vector<int>num1{ 1, 3, 5, 7, 9 };
	vector<int>num2{ 2, 4, 6, 8, 10 };
	vector<int>result;		//结果
	result.resize(num1.size());//分配大小
	transform(num1.begin(), num1.end(), num2.begin(), result.begin(), function<int>());
	//transform将两个范围的内容相乘,存储在第3个范围内

  14.6 二元谓词

    class function		//在类中实现		
    {
    public:
    	bool operator()(const string& str1,const string& str2)const
    	{			//不区分大小写,字符串比较
    		string s1;
	    	s1.resize(str1.size());
	    	transform(str1.begin(), str1.end(), s1.begin(), ::tolower);//转小写字母
	    	string s2;
	    	s2.resize(str2.size());
	    	transform(str2.begin(), str2.end(), s2.begin(), ::tolower);//转小写字母
	    	return(s1 < s2);//字符串不区分大小写排序(由小到大)
	    }
    };
	vector<string>name;
	name.push_back("jam");
	name.push_back("Jank");
	name.push_back("Sam");
	name.push_back("Anna");
	sort(name.begin(), name.end(), function());//排序(默认时,区分大小写)
	for (auto i = name.begin(); i != name.end(); ++i)
		cout << *i << endl;

  14.7 lambda表达式

[var1,var2]<typename T1, typename T2>(T1 param1,T2 param2){function} -> returntype
	//[var1,var2]表示捕获的变量,传递给lambda表达式使用
	//<typename T1, typename T2>表示模板参数列表
	//(T1 param1,T2 param2)表示输入的参数值
	//{function}表示函数代码
	//-> returntype表示返回值类型
vector<int>num{ 1, 2, 3, 4, 5 };
auto labmda = [](const int& element){cout << element << ' '; };
for_each(num.begin(), num.end(), labmda);//1、一元函数对应的lambda表达式	
for_each(num.begin(), num.end(), [](const int& element){cout << element << ' '; });
											 //2、一元谓词对应的lambda表达式
auto p1 = find_if(num.begin(),num.end(),[](const int& num){return ((num % 2) == 0);});

int var;//3、要使用lambda表达式外面的变量,称为捕获列表[var1,var2...]
auto p2 = find_if(num.begin(), num.end(),[var](const int& num){return((num%var) == 0);});
			//如果要对该捕获的变量进行修改,则加关键字mutable
auto p3 = find_if(num.begin(), num.end(),[var](const int& num)mutable{return((num%var)== 0);});

  14.8 二元函数的lambda表达式

	vector<int> num1{ 0, 1, 2, 3, 4 };
	vector<int>num2{ 10, 20, 30, 40, 50 };
	vector<int>result;
	result.resize(num1.size());//二元函数对应的lambda表达式
    transform(num1.begin(),num1.end(),num2.begin(),result.begin(),[](int a,int b){return a*b;});

  14.9 二元谓词的lambda表达式

	vector<string>name{ "jam", "Jank", "Sam", "Anna" };
	sort(name.begin(), name.end(), 
		[](const string& str1, const string& str2) ->bool //显示返回bool类型
		{			//不区分大小写,字符串比较
			string s1,s2;
			s1.resize(str1.size());
			s2.resize(str2.size());
			transform(str1.begin(), str1.end(), s1.begin(), ::tolower);//转小写字母
			transform(str2.begin(), str2.end(), s2.begin(), ::tolower);//转小写字母
			return(s1 < s2);//字符串不区分大小写排序(由小到大)
		}
	);

第15 章 STL算法

  15.1 find() 和 find_if()

        根据值或条件查找元素:

    vector<int> num{ 1, 2, 3,10, 4, 5, 6, 7, 8, 9, 10 };
    auto element = find(num.begin(), num.end(), 10);//1、find()查找值为10的第一个元素
    if (element != num.end())	//检查是否找到
    	cout << distance(num.begin(), element)<<" : " << *element << endl;
											//2、find_if()查找满足lambda表达式的第一个元素
    auto element1 = find_if(num.begin(), num.end(), [](int n){return ((n % 2) == 0); });
    if (element1 != num.end())	//检查是否找到
	    cout << distance(num.begin(), element1) << " : " << *element1 << endl;

  15.2 count() 和 count_if()

        计算包含给定值或满足给定条件的元素数量:

	vector<int> num{ 1, 2, 3,10, 4, 5, 6, 7, 8, 9, 10 };
	size_t n1 = count(num.begin(), num.end(), 10);
	cout << "值为10的元素数量:" << n1 << endl;
	size_t n2 = count_if(num.begin(), num.end(), [](int n){return((n % 2) == 0); });
	cout << "值为偶数元素数量:" << n2 << endl;

  15.3 search() 和 search_n()

        在集合中搜索元素或序列:

	vector<int> num1{ 1, 2, 3, 4, 5, 6, 7, 8, 8, 8, 8, 9, 10 };
	list<int> num2{  6, 7 ,8};
	auto n1 = search(num1.begin(), num1.end(), num2.begin(), num2.end());//查找list序列
	if (n1 != num1.end())
		cout << distance(num1.begin(),n1) << endl;
	auto n2 = search_n(num1.begin(), num1.end(), 4, 8);//查找4个8的序列
	if (n2 != num1.end())
		cout << distance(num1.begin(), n2) << endl;

  15.4 fill() 和 fill_n()

        将容器中的元素初始化为指定值:

	vector<int> num(10);
	fill(num.begin(), num.end(), 6);//将范围内所有元素填充为6
	for (size_t index = 0; index < num.size(); ++index)
		cout << num[index] << " ";
	cout << endl;

	fill_n(num.begin() + 3, 4, 9);//(起始位置,数量,填充的值)
	for (size_t index = 0; index < num.size(); ++index)
		cout << num[index] << " ";
	cout << endl;

  15.5 generate() 和 generate_n()

        将元素设置为运行阶段生成的值:

	#include<ctime>
    srand(static_cast<int>(time(NULL)));	//使用时间time作为随机数种子

	vector<int> num1(10);
	generate(num1.begin(), num1.end(),rand);	//给容器中所有元素生成随机数
	for (size_t n = 0; n < num1.size(); ++n)
		cout << num1[n] << " ";

	list<int>num2(10);
	generate_n(num2.begin(), 5, rand);	//给容器中前5个元素生成随机数
	for (auto n = num2.begin(); n != num2.end(); ++n)
		cout << *n << " ";

  15.6 for_each()

        处理指定范围内的元素:

	template<typename T>
    struct Displayelement
    {
    	int count;
    	Displayelement() :count(0){}
    	void operator()(const T& n)
    	{
    		++count;
    		cout << n << " ";
    	}
    };
    vector<int>num{ 1, 2, 3, 4, 5, 6 };
	// for_each()对指定范围内每个元素执行一元函数对象,返回函数对象
	Displayelement<int> n = for_each(num.begin(), num.end(), Displayelement<int>());
	cout << endl << n.count << endl;

	string str("abcdefghijklmnopqrstuvwxyz");
	int len = 0;
	//使用lambda表达式代替一元函数对象
	for_each(str.begin(), str.end(), [&len](char c){cout << c << " "; ++len; });
	cout << endl << len << endl;

  15.7 transform()

        对范围内进行变换:

	string str("ThiS Is a tEst sTriNg!");
	string str1;
	str1.resize(str.size());
	transform(str.begin(), str.end(), str1.begin(), ::tolower);	//将str转换为小写,保存在str1中
	cout << str1 << endl;

	vector<int> num1{ 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	vector<int> num2(num1.size(), 10);	//全部初始化为10
	deque<int>result(num1.size());		//存放结果
	transform(num1.begin(), num1.end(), num2.begin(), result.begin(), plus<int>());
										//STL函数plus()将两个元素相加
	for (size_t index = 0; index < num1.size(); ++index)
		cout << result[index] << " ";

  15.8 copy()、copy_if() 和 remove()、remove_if()

        复制copy()、copy_if(),删除remove()、remove_if():

	template<typename T>
    void Display(const T& num)
    {
    	for_each(num.begin(), num.end(), [](const auto&element){cout << element << " "; });
    	cout << endl << "number:" << num.size() << endl;
    }

    list<int> num{ 0, 1, 2, 3, 4, 5, 6 };
	Display(num);
	vector<int>num1(num.size()*2);
	auto lastelement = copy(num.begin(), num.end(), num1.begin());//1、num全部copy到num1,返回最后元素的迭代器 
	copy_if(num.begin(), num.end(), lastelement, [](int element){return ((element % 2) != 0); });
											//2、num中奇数copy到num1,num1从上次结束位置开始
	Display(num1);
	
	auto newend = remove(num1.begin(),num1.end(),0);	//3、删除值为0的元素,删除后向前整理元素 
	num1.erase(newend,num1.end());						//num1.end()值不变,newend为新的末尾位置
	
	newend = remove_if(num1.begin(),num1.end(),[](int element){return ((element % 2) != 0);});
	num1.erase(newend,num1.end());		//4、remove_if(),删除满足谓词的元素,使用lambda表达式 
	Display(num1); 

  15.9 replace() 和 replace_if()

        替换值或替换满足给定条件的元素:

vector<int> num{ 1, 2, 3, 1, 5, 6 };
replace(num.begin(), num.end(), 1, 100);//值为1的元素,将其值替换为100
Display(num);
replace_if(num.begin(), num.end(), [](int element){return ((element % 2) != 0); },-1);
Display(num);				//使用lambda表达式,将满足谓词的元素其值替换为-1 

  15.10 sort() 和 unique() 和 binary_search()

        对集合进行排序sort,在有序集合中搜索binary_search或删除重复元素unique:

	vector<int> num{ 1, 3, 2, 1, 6, 4 };
	sort(num.begin(), num.end());						//默认从小到大 
	Display(num);
	sort(num.begin(), num.end(),[](int a,int b){return a>b;});//指定谓词,由大到小 
	Display(num);
	
	bool found = binary_search(num.begin(),num.end(),2);//在有序容器中查找值为2的元素 
	if(found)cout<<"YES"<<endl;
	else cout<<"NO"<<endl; 
	
	auto newend = unique(num.begin(),num.end());//删除相邻的重复元素 
	num.erase(newend,num.end()); 			//调整容器大小 
	Display(num);

  15.11 partition()  和 stable_partition()

        将范围分区:

auto condition = [](const int& num){return ((num%2)==0);};	//一元谓词 
template<typename T>
void Display(const T& num)
{
	for_each(num.begin(), num.end(), [](const auto&element){cout << element << " "; });
	cout << endl << "number:" << num.size() << endl;
}
int main()
{

	vector<int> num1{ 1, 3, 2, 1, 6, 4 };
	vector<int> num2(num1);
	partition(num1.begin(),num1.end(),condition);	//偶数在前,奇数在后 
	Display(num1);
	stable_partition(num2.begin(),num2.end(),condition);//不改变元素的先后顺序 
	Display(num2);
	return 0;
}

  15.12 lower_bound() 和 upper_bound()

        在有序集合中插入元素:


    list<int> num{ 1, 3, 2, 1, 6, 4 };
	num.sort();
	Display(num); 
	auto minpos = lower_bound(num.begin(),num.end(),1);		//lower返回最小插入位置,不进行插入操作 
	cout<<"min position = "<<distance(num.begin(),minpos)<<endl;
	auto maxpos = upper_bound(num.begin(),num.end(),1);		//upper返回最大插入位置,不进行插入操作
	cout<<"max position = "<<distance(num.begin(),maxpos)<<endl;
	num.insert(maxpos,1);									//插入 
	Display(num); 
插入的值在有序表中不存在时,lower和upper返回值相同

  15.13 C++20 accumulate()

        执行累积操作:

	#include<numeric>    //accumulate头文件
    vector<int> num{1,2,3,4,5,6,7,8,9};
	int sum = accumulate(num.begin(),num.end(),0);//累加操作,初值为0 ,返回累加之和 
	cout<<sum<<endl; 							//二元谓词,返回累乘 
	int product = accumulate(num.begin(),num.end(),1,[](auto a,auto b){return a*b;});
	cout<<product<<endl;

  15.14 C++20约束算法

         前面介绍的所有算法都需要显示的指定范围,C++20使用算法的约束版本,位于命名空间std::ranges中,约束版本只需指明容器对象,不用指定范围的起始和结束。

	vector<int> num{9,8,7,6,5,4,3,2,1,0};
	Display(num);
	
	auto element = ranges::find(num,1);	//ranges::find查找 
	if(element != num.end())cout<<"find"<<endl;
	else cout<<"no find"<<endl;
	
	ranges::sort(num);					//ranges::sort排序 
	Display(num);
	
	ranges::fill(num,0);				//ranges::fill填充 
	Display(num);
	
	string str("HELLO WORLD");
	ranges::for_each(str,[](auto& c){c = ::tolower(c);});//ranges::for_each改变大小写 
	Display(str);

第16 章 自适应容器:栈和队列

  16.1 栈stack

       自适应容器指使用另一种容器实现自己的容器, stack是一个泛型类,允许在顶部插入和删除元素,不允许访问中间元素

template<class _Ty,                    //参数1:stack存储的对象类型
	class _Container = deque<_Ty>      //参数2:stack默认使用容器deque存储数据
    >class stack;
1、实例化stack
    stack<int>num1;				//1、int类型,存储使用默认deque<int>
	stack<int, vector<int>>num2;//2、int类型,存储使用指定vector<int>
	stack<int>num3(num1);		//3、使用另一stack初始化
2、stack的成员函数
    //stack改变了其它容器的行为,限制插入删除方式保证栈的特性
    #include<stack>
	stack<int>num;				
	num.push(11);			//1、push(),在栈顶插入元素
	num.push(22);
	num.push(33);
	while (num.size() != 0)	//2、size(),返回栈中的元素数
	{
		cout << "Top : " << num.top() << endl;//3、top(),获得指向栈顶元素的引用
		num.pop();			//4、pop(),删除栈顶元素
	}
	if (num.empty())		//5、empty(),检查栈是否为空,返回布尔值
		cout << "stack is empty!" << endl;

  16.2 队列queue

        queue是一个模板类和泛型类,只允许在末尾插入元素,在开头删除元素,不允许访问中间的元素,可以访问开头和末尾的元素

template<class _Ty,                //参数1:queue元素类型
	class _Container = deque<_Ty>  //参数2:默认deque存储数据
    >class queue;
1、实例化queue
	queue<int>num1;				//1、元素类型int,存储默认deque<int>
	queue<int, list<int>>num2;	//2、元素类型int,存储指定list<int>
	queue<int>num3(num1);		//3、使用另一queue初始化
2、queue的成员函数
	#include<queue>
	queue<int>num;
	num.push(10);			//1、push(),在队尾插入元素
	num.push(20);
	num.push(30);
	cout << num.size() << endl;	//2、size(),返回队列中的元素数量
	cout << num.front() << endl;//3、front(),返回指向队首元素的引用
	cout << num.back() << endl; //4、back(),返回指向队尾元素的引用
	while (num.size() != 0)
	{
		cout << num.front() << endl;
		num.pop();				//5、pop(),将队首的元素删除
	}
	if (num.empty())			//6、empty(),检查队列是否为空,并返回布尔值
		cout << "queue is empty!" << endl;

  16.3 优先级队列priority_queue

         与queue不同之处:最大值在队首,且只能在队首执行操作

template<class _Ty,                    //参数1:元素类型
	class _Container = vector<_Ty>,    //参数2:默认使用vector存储数据
	class _Pr = less<typename _Container::value_type>//参数3:二元谓词,默认less,由大到小
	>class priority_queue;
1、实例化priority_queue
    #include<queue>
    #include<functional>
    priority_queue<int>num1;		
	priority_queue<int,deque<int>,greater<int>>num2;//指定谓词std::greater,最小元素位于队首
	priority_queue<int>num3(num1);
2、priority_queue成员函数
    priority_queue<int>num;		
    //priority_queue<int, deque<int>, greater<int>>num;
	num.push(10);			      //1、push(),在优先级队列中插入元素
	num.push(20);
	cout << num.size() << endl;	  //2、size(),返回优先级队列中的元素数量
	while (!num.empty())	      //3、empty(),检查优先级队列是否为空,并返回布尔值
	{
		cout << num.top() << endl;//4、top(),返回队列最大元素(队首元素)的引用
		num.pop();				  //5、pop(),将队首的元素删除
	}

  16.4 bitset类

        bitset是一个STL类,处理以位序列和位标志表示的信息,不是STL容器类不能调整长度

1、实例化bitset	
    #include<bitset>
    bitset<4>num1;			//1、 4bits,初始化为二进制0000
	bitset<5>num2("10101"); //2、 5bits,初始化为二进制10101
	bitset<6>num3(0b101010);//3、 6bits,初始化为二进制101010
	bitset<8>num3(255);		//4、 8bits,初始化为二进制11111111
	bitset<8>num4(num3);	//5、 使用另一bitset进行初始化
2、使用bitset成员
    bitset运算符:
	    1、运算符<<:将位序列的文本表示插入输出流
	    2、运算符>>:将一个字符串插入bitset对象
	    3、运算符&: 按位与
	    4、运算符|: 按位或
	    5、运算符^: 按位异或
	    6、运算符~: 按位反
	    7、运算符>>=:按位右移
	    8、运算符<<=:按位左移
	    9、运算符[n]:返回第n个位的引用(|=、 &=、 ^=、 ~=等)
    bitset成员方法:
	    set():将所有位设置为1
	    set(n,val=1):将第n位设置为val,val默认为1
	    reset():将序列中的所有位重置为0
	    reset(n):清除第n位
	    flip():所有位取反
	    size():返回序列中的位数
    	count():返回序列中值为1的位数

	bitset<4>num1("1010");
	bitset<4>num2("0111");
	num1.count();//1的位数
	num1.size();//总位数
	num1.flip();//所有位取反
	num1.set();//所有位设置1
	cout << (num1&num2) << endl;//与
	cout << (num1|num2) << endl;//或
	cout << (num1^num2) << endl;//异或

  16.5 vector<bool>

         由于bitset不能动态调整长度,因此可以使用vector<bool>类

	vector<bool>num1;			//1、初始化
	vector<bool>num2(10, true); //2、初始化,10个元素为ture
	vector<bool>num3(num2);		//3、用另一实例化进行初始化

	vector<bool>num{ true, true, false };//参数列表初始化
	num[0] = false;				//以数组方式[]访问
	num.push_back(true);		//与vector相类似,使用push_back()插入
	num.size();					//长度
	num.flip();					//取反
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值