第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(); //取反