#include<iostream>
using namespace std;
#include<stack>
#include<queue>
#include<string>
#include<list>
#include<set> //含有set和multiset
#include<map>
/*stack容器
*先进后出 (First in First out)
*有一个出口,只有栈顶top元素才可以被外界使用
因此,栈不允许有遍历行为
入栈push
出栈pop
*/
/*stack常用接口
功能描述:栈容器常用的对外接口
构造函数:
stack<T> stk; //stack采用模板类实现,stack对象的默认构造形式
stack<const stack &stk> ; //拷贝构造函数
赋值操作:
stack& operator=(const stack &stk); //重载等号操作符
数据存取:
push(elem); //向栈顶添加元素
pop(); //从栈顶移除第一个元素
top(); //返回栈顶元素
大小操作:
empty(); //判断堆栈是否为空
size(); //返回栈的大小
*/
void test_stack_01()
{
stack<int>s;
//入栈
s.push(10);
s.push(20);
s.push(30);
s.push(40);
//只要栈不为空,查看栈顶,并且执行出栈操作
while (!s.empty())
{
//查看栈顶元素
cout<< "栈顶元素为:" << s.top() <<endl;
//出栈
s.pop();
}
cout << "栈的大小:" << s.size() <<endl;//全部出栈,大小为0
}
/*queue容器
*先进先出(First in first out)
*它有两个出口 ,队头和队尾,但队头只能出 ,队尾只能进 ,不允许有遍历行为
入队: push
出队: pop
*/
/*queue常用接口
功能描述:队列容器常用的对外接口
构造函数:
queue<T> que; //queue采用模板类实现,queue对象的默认构造形式
queue<const queue &que> ; //拷贝构造函数
赋值操作:
queue& operator=(const queue &que); //重载等号操作符
数据存取:
push(elem); //向队尾添加元素
pop(); //从队头移除第一个元素
back(); //返回最后一个元素
front(); //返回第一个元素
大小操作:
empty(); //判断队列是否为空
size(); //返回队列的大小
*/
class Man {
public:
Man(string name, int age)
{
this->m_Name = name;
this->m_Age = age;
}
string m_Name;
int m_Age;
};
void test_queue_01()
{
queue<Man>q;
Man m1("唐僧", 30);
Man m2("孙悟空",1000);
Man m3("猪八戒",900);
Man m4("沙僧",800);
//入队
q.push(m1);
q.push(m2);
q.push(m3);
q.push(m4);
cout << "队列大小为:" << q.size() << endl;
//判断只要队列不为空,查看队头,查看队尾,出队
while (!q.empty())
{
//查看队头
cout<<"队头元素 姓名:"<< q.front().m_Name << " 队头元素 年龄:" << q.front().m_Age << endl;
//查看队尾
cout << "队尾元素 姓名:" << q.back().m_Name << " 队尾元素 年龄:" << q.back().m_Age << endl;;
//出队
q.pop();
}
cout << "队列大小为:" <<q.size() <<endl;
}
/*list容器
功能描述:将数据进行链式存储 插入删除快,遍历慢
*链表(list):是一种物理存储单元上非连续的存储结构,数据元素的逻辑顺序是通过链表中的指针链接实现的
*一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域
*STL中的链表是一个双向循环链表 (最后一个节点后驱记录第一个节点地址,第一个节点前驱记录最后一个节点地址)
*由于链表的存储方式不是连续的内存空间,一次链表list中的迭代器只支持前移和后移,属于双向迭代器
*重要性质:插入和删除操作都不会造成原有list迭代器的失效,这在vector是不成立的
list和vector是最常用的两个容器,各有优缺点
*/
/*list构造函数
list<T> lst; //list采用模板类实现,对象的默认构造形式
list(beg,end); //构造函数将[beg,end)区间中的元素拷贝给本身
list(n,elem); //构造函数将n个elem拷贝给本身
list(const list &lst); //拷贝构造函数
*/
void printList(const list<int> &L) //为了在打印时不修改它const
{
for (list<int>::const_iterator it = L.begin(); it != L.end(); it++)
{
cout<< *it <<" ";
}
cout<<endl;
}
void test_list_01()
{
//创建list容器
list<int>L1;
//添加数据
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
L1.push_back(40);
//遍历容器
printList(L1);
//区间方式构造
list<int>L2(L1.begin(),L1.end());
printList(L2);
//拷贝构造
list<int>L3(L1);
printList(L3);
//n个elem
list<int>L4(10, 100);
printList(L4);
}
/*list 赋值和交换
功能描述: 给list容器进行赋值,以及交换list容器
assign(beg,end); //将[beg,end)区间中的数据拷贝赋值给本身
assign(n,elem); //将n个elem拷贝赋值给本身
list& operator=(const list &lst); //重载等号操作符
swap(lst); //将lst与本身的元素互换
*/
void test_list_value_01()
{
list<int>L1;
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
L1.push_back(40);
printList(L1);
//等号赋值
list<int>L2 = L1;
printList(L2);
//assign赋值
list<int>L3;
L3.assign(L1.begin(),L1.end());
printList(L3);
//assign赋值
list<int>L4;
L4.assign(10,100);
printList(L4);
cout << "交换前:"<< endl;
printList(L1);
printList(L4);
L1.swap(L4);
cout<< "交换后:"<< endl;
printList(L1);
printList(L4);
}
/*list大小的操作
empty(); //判断容器是否为空
size(); //返回容器中元素的个数
resize(int num) //重新指定容器的长度num,若容器变长,则以默认值填充新位置
//如果容器变短,则末尾超出容器长度的元素被删除
resize(int num,elem) //重新指定容器的长度num,若容器变长,则以elem填充新位置
//如果容器变短,则末尾超出容器长度的元素被删除
*/
void test_list_capacity_01()
{
list<int>L1;
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
L1.push_back(40);
printList(L1);
if (L1.empty())
{
cout<< "L1为空"<<endl;
}
else
{
cout << "L1不为空" << endl;
cout << "L1元素个数:" << L1.size()<<endl;
}
//重新指定大小
L1.resize(10, 10000);
printList(L1);
L1.resize(2);
printList(L1);
}
/*list插入和删除
push_back(elem); //在容器尾部加入一个元素
pop_back(); //删除容器中最后一个元素
push_front(elem); //在容器开头插入一个元素
pop_front(); //从容器开头移除一个元素
insert(pos,elem); //在pos位置插入元素elem的拷贝,返回新数据的位置
insert(pos,n,elem); //在pos位置插入n个元素elem的拷贝,无返回值
insert(pos,beg,end); //在pos位置插入[beg,end)区间的数据,无返回值
clear(); //移除容器的所有数据
erase(beg,end); //删除[beg,end)区间的数据,返回下一个数据的位置
erase(pos); //删除pos位置的数据,返回下一个数据的位置
remove(elem); //删除容器中所有与elem值匹配的元素
*/
void test_list_insert_delete_01()
{
list<int>L1;
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
L1.push_front(100);
L1.push_front(200);
L1.push_front(300);
printList(L1);//300 200 100 10 20 30
//尾部删除
L1.pop_back();
L1.pop_front();
printList(L1);//200 100 10 20
//头部插入
list<int>::iterator it = L1.begin();
L1.insert(++it,1000);//偏移后插入
printList(L1);//200 1000 100 10 20
//删除
it = L1.begin();
L1.erase(++it);//偏移后删除
printList(L1);//200 100 10 20
//移除
L1.push_back(10000);
L1.push_back(10000);
L1.push_back(10000);
L1.push_back(10000);
printList(L1); //200 100 10 20 10000 10000 10000 10000
L1.remove(10000);
printList(L1); //200 100 10 20
//清空
L1.clear();
printList(L1);
}
/*list数据存取
front(); //返回第一个元素
back(); //返回最后一个元素
list容器不能用[]或at方式访问
*/
void test_list__find()
{
list<int>L1;
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
L1.push_back(40);
//L1[0] 不可以用[] 访问list容器中的元素
//L1.at(0) 不可以用at方式访问list容器中的元素
//原因是list本质是链表,不是连续线性空间存储数据,迭代器也是不支持随机访问的
cout << "第一个元素:" << L1.front()<<endl;
cout<< "最后一个元素:" << L1.back() <<endl;
//验证迭代器是不支持随机访问的
list<int>::iterator it = L1.begin();
//it = it + 1; //错误,没有与这些操作数匹配的“+”运算符 ,验证不支持随机访问
it++;//可以往前或往后走 ,验证支持双向 it++,it-- ,(同理可验证其他容器)
}
/*list容器反转和排序
功能描述:将容器中的元素反转,以及将容器中的数据进行排序
reverse();//反转链表
sort(); //链表排序
*/
bool myCompare(int value1,int value2)//回调函数
{
//降序 就让第一个数 > 第二个数
return value1 > value2;
}
void test_list_reverse_01()
{
list<int>L1;
L1.push_back(20);
L1.push_back(10);
L1.push_back(50);
L1.push_back(40);
L1.push_back(30);
cout<< "反转前:"<<endl;
printList(L1);
//反转
cout << "反转后:" << endl;
L1.reverse();//成员函数
printList(L1);
//排序
cout << "排序前:" << endl;
printList(L1);
//所有不支持随机访问迭代器的容器,不可以用标准算法
//不支持随机访问迭代器的容器,内部会提供一些算法
L1.sort();//默认升序 从小到大
cout << "排序后:" << endl;
printList(L1);
L1.sort(myCompare); //通过自己写的函数,让sort变成降序,从大到小
}
/*排序案例
案例描述: 将Person自定义数据类型进行排序,Person中属性有姓名、年龄、身高
排序规则:按照年龄进行升序,如果年龄相同按照身进行降序
*/
class Person {
public:
Person(string name,int age,int height)
{
this->m_Name = name;
this->m_Age = age;
this->m_Height = height;
}
int m_Age;
string m_Name;
int m_Height;
};
//指定排序规则,自己写回调函数
bool comparePerson(Person& p1, Person& p2)
{
//按照年龄 升序
if (p1.m_Age == p2.m_Age)//高级排序
{
return p1.m_Height > p2.m_Height;
}
return p1.m_Age < p2.m_Age;
}
void test_list_example()
{
list<Person>L;
Person p1("刘备",35 ,175 );
Person p2("曹操",45 ,180 );
Person p3("孙权",40 ,170 );
Person p4("赵云",25 ,190 );
Person p5("张飞",35 ,160 );
Person p6("关羽",35 ,200 );
//插入数据
L.push_back(p1);
L.push_back(p2);
L.push_back(p3);
L.push_back(p4);
L.push_back(p5);
L.push_back(p6);
for (list<Person>::iterator it = L.begin(); it != L.end(); it++)
{
cout<<"姓名:" << (*it).m_Name << "年龄:"<< (*it).m_Age <<"身高:" << (*it).m_Height <<endl;
}
//排序
cout << "--------------------------" << endl;
cout<< "排序后:" <<endl;
L.sort(comparePerson);
for (list<Person>::iterator it = L.begin(); it != L.end(); it++)
{
cout << "姓名:" << (*it).m_Name << "年龄:" << (*it).m_Age << "身高:" << (*it).m_Height << endl;
}
}
/* set / multiset 容器 //包含一个set头文件就可以用两种
*简介:所有元素都会在插入时自动排序
*本质:set / multiset 容器属于关联式容器,底层结构是二叉树实现
*set/multiset 的区别:
set不允许容器中有重复的元素
multiset允许容器中有重复的元素
*/
/*set容器的构造和赋值
功能描述:创建set容器以及赋值
构造:
set<T> st //默认构造函数
set<const set &st>; //拷贝构造函数
赋值:
set & operator=(const set &st); //重载等号操作符
*/
void printSet(set<int> &s)
{
for (set<int>::iterator it = s.begin(); it != s.end(); it++) //用迭代器
{
cout<< *it <<" ";
}
cout << endl;
}
void test_set_01()
{
set<int>s1;
//插入数据只有insert方式
s1.insert(10);
s1.insert(40);
s1.insert(20);
s1.insert(30);
s1.insert(30);
//遍历容器
//set容器特点:所有元素插入时候被自动排序
//set容器不允许插入重复值,不会报错,但无效插入
printSet(s1);
//拷贝构造
set<int>s2(s1);
printSet(s2);
//赋值
set<int>s3(s2);
printSet(s3);
}
/*set大小和交换
size(); //返回容器中元素的数目
empty(); //判断容器是否为空
swap(st); //交换两个集合容器
*/
void test_set_capacity_01()
{
set<int>s1;
s1.insert(10);
s1.insert(20);
s1.insert(30);
s1.insert(40);
printSet(s1);
//判断是否为空
if (s1.empty())
{
cout<< "s1为空" <<endl;
}
else
{
cout << "s1不为空" << endl;
cout << "s1的大小:" << s1.size() << endl;
}
set<int>s2;
s2.insert(40);//set自动排序
s2.insert(30);
s2.insert(20);
s2.insert(10);
s2.insert(50);
cout << "交换前" << endl;
printSet(s1);
printSet(s2);
s2.swap(s1);
cout << "交换后" << endl;
printSet(s1);
printSet(s2);
}
/*set插入和删除
insert(elem); //在容器中插入元素
clear(); //清除所有元素
erase(pos); //删除pos迭代器所指的元素,返回下一个元素的迭代器
erase(beg,end); //删除区间[beg,end)的所有元素,返回下一个元素的迭代器
erase(elem); //删除容器中值为elem的元素
*/
void test_set_insert_delete_01()
{
set<int>s1;
s1.insert(10);
s1.insert(20);
s1.insert(30);
s1.insert(40);
printSet(s1);
//删除
s1.erase(s1.begin());
printSet(s1);
//删除重载版本
s1.erase(30);
printSet(s1);
//清空
//s1.erase(s1.begin(),s1.end());
s1.clear();
printSet(s1);
}
/*set查找和统计
find(key); //查找key是否存在,若存在,返回该键的元素的迭代器,若不存在,返回set.end()
count(key); //统计key元素的个数
*/
void test_find_01()
{
set<int>s1;
s1.insert(10);
s1.insert(20);
s1.insert(30);
s1.insert(40);
set<int>::iterator pos = s1.find(30);
if (pos != s1.end())
{
cout<< "找到元素: "<< *pos << endl;
}
else
{
cout << "未找到元素 " << endl;
}
int num = s1.count(30);
//对于set而言,结果要么0,要么1
cout << "num = " << num <<endl;
}
/*set与multise区别
multise允许插入重复值,set不允许
set插入数据的同时会返回插入结果,表示插入是否成功
multise不会检测数据,因此可以插入重复数据
*/
void test_different_01()
{
set<int>s1;
pair<set<int>::iterator ,bool> ret = s1.insert(10); //返回值bool型 **等式赋值过程中执行了s1的插入
if (ret.second)
{
cout<<"第一次插入成功" <<endl;
}
else
{
cout << "第一次插入失败" << endl;
}
ret = s1.insert(10);//第二次插入
if (ret.second)//返回值
{
cout << "第二次插入成功" << endl;
}
else
{
cout << "第二次插入失败" << endl;
}
multiset<int>ms;
ms.insert(10);
ms.insert(10);
ms.insert(10);
ms.insert(10);
for (multiset<int>::iterator it = ms.begin(); it != ms.end(); it++)
{
cout<< *it << " " ;
}
cout<<endl;
}
/*pair对组创建 不需要头文件
*功能描述:成对出现的数据,利用对组可以 返回两个数据
两种创建方式:
pair<type,type> p (value1,value2);
pair<type,type> p = make_pair(value1,value2);
*/
void test_pair_01()//记住一种即可
{
//第一种方式
pair<string, int>p("Tom",20);
cout<< "姓名:" << p.first << "年龄:"<< p.second<<endl;
//第二种方式
pair<string, int>p2 = make_pair("Jerry", 10);
cout << "姓名:" << p2.first << "年龄:" << p2.second << endl;
}
/*set容器排序
set容器默认排序从小到大
利用仿函数,可以改变排序规则
*/
class Mycompare {
public:
bool operator()(int v1 ,int v2) const //operator()重载的符合 ,第二个(前一个,后一个)放参数比较(看比较数据的类型)
{
return v1 > v2;//前面的数大于后面的数
}
};
void test_change_sort_01()
{
set<int>s1;
s1.insert(50);
s1.insert(40);
s1.insert(10);
s1.insert(20);
s1.insert(30);
for (set<int>::iterator it = s1.begin(); it != s1.end(); it++) // <int>
{
cout << *it << " ";
}
cout << endl;
/* C3848 在仿函数中加入const 解决
//指定排序规则为从大到小
set<int,Mycompare>s2; //仿函数本质是一个类型
s2.insert(10);
s2.insert(40);
s2.insert(20);
s2.insert(50);
s2.insert(30);
for (set<int, Mycompare>::iterator it = s2.begin(); it != s2.end(); it++) //<int, Mycompare>
{
cout << *it << " ";
}
cout << endl;
*/
}
//set容器排序,存放自定义数据类型
class Person_1 {
public:
Person_1(string name, int age)
{
this->m_Name = name;
this->m_Age = age;
}
int m_Age;
string m_Name;
};
class comparePerson_1 {
public:
bool operator()(const Person_1& p1, const Person_1& p2)const
{
//按照年龄 降序
return p1.m_Age > p2.m_Age;
}
};
void test_sort_02()
{
//自定义的数据类型 都要指定排序规则 写仿函数
set<Person_1, comparePerson_1>s;
Person_1 p1("刘备", 24);
Person_1 p2("关羽", 28);
Person_1 p3("张飞", 25);
Person_1 p4("赵云",21);
s.insert(p1);
s.insert(p2);
s.insert(p3);
s.insert(p4);
for (set<Person_1, comparePerson_1>::iterator it = s.begin();it != s.end();it++) //类自创类型
{
cout<< "姓名:" << it->m_Name << " 年龄:" << it ->m_Age <<endl;
}
}
/*map/multimap容器构造和赋值 使用频率次高
简介:
map中所有元素都是pair
pair中的第一个元素为key(键值),起到索引作用,第二个元素为value(实值)
所有元素都会根据元素的键值自动排序
本质:
map/multimap 属于关联式容器,底层结构是二叉树实现
优点:
可以根据key值快速找到value值
map和multimap区别
map不允许容器中有重复的key值元素 (value都允许重复)
multimap允许容器中有重复的key值元素
*/
void printMap(map<int, int> &m)
{
for (map<int,int>::iterator it = m.begin();it != m.end();it++)
{
cout<< "key = " << (*it).first << " value = " << it->second << endl; //用 (*it). 或 it->
}
cout<<endl;
}
void test_map_01()
{
//创建map容器
map<int, int>m;
m.insert(pair<int, int>(1, 10));
m.insert(pair<int, int>(3, 30));
m.insert(pair<int, int>(2, 20));
m.insert(pair<int, int>(4, 40));
printMap(m); // 会按照key做排序 key 1 , 2 , 3 ,4
//拷贝构造
map<int, int>m2(m);
printMap(m2);
//赋值
map<int, int>m3;
m3 = m2;
printMap(m3);
}
/*map大小和交换
size(); //返回容器中元素的数目
empty(); //判断容器是否为空
swap(m); //交换两个集合容器
*/
void test_map_size_01()
{
map<int, int>m;
m.insert(pair<int, int>(1, 10));
m.insert(pair<int, int>(2, 20));
m.insert(pair<int, int>(3, 30));
if (m.empty())
{
cout<< "m为空 "<<endl;
}
else
{
cout << "m不为空 " << endl;
cout << "m的大小为: " << m.size() <<endl;
}
map<int, int>m2;
m2.insert(pair<int, int>(4, 100));
m2.insert(pair<int, int>(5, 200));
m2.insert(pair<int, int>(6, 300));
cout << "交换前 " << endl;
printMap(m);
printMap(m2);
m.swap(m2);
cout << "交换后 " << endl;
printMap(m);
printMap(m2);
}
/*map插入和删除
insert(elem); //在容器中插入元素
clear();
erase(pos); //删除pos迭代器所指的元素,返回下一个元素的迭代器
erase(beg,end); //删除区间[beg,end)的所有元素,返回下一个元素的迭代器
erase(key); //删除容器中值为key的元素
*/
void test_insert_delete_01()
{
map<int, int>m;
//插入
//第一种
m.insert(pair<int, int>(1, 10));
//第二种
m.insert(make_pair(2, 20));//记第一、二种好记
//第三种
m.insert(map<int, int>::value_type(3, 30));//map作用域下的值类型
//第四种 []用于key找到value
m[4] = 40; //最简单,但不建议[]
printMap(m);
//* cout<< m[5] <<endl;//若插错了或写一个不存在的key ,没赋值的位置会创建一个0
//删除
m.erase(m.begin());
printMap(m);
m.erase(3);//只会按照key删 m.erase(30)没有key为30 无效
printMap(m);
//m.erase(m.begin(),m.end());
m.clear();
printMap(m);
}
/*map查找和统计
find(key) //查找key是否存在,若存在,返回该键的元素的迭代器,若不存在,返回set.end();
count(key); //统计key的元素个数
*/
void test_map_count_01()
{
//查找
map<int, int>m;
m.insert(pair<int, int>(1, 10));
m.insert(pair<int, int>(2, 20));
m.insert(pair<int, int>(3, 30));
m.insert(pair<int, int>(3, 40));
map<int, int>::iterator pos = m.find(3);
if (pos != m.end())
{
cout<<"查找到了元素 key = " << (*pos).first<< " value = "<< pos->second <<endl;
}
else
{
cout<< "未找到元素"<<endl;
}
//统计
//map不允许插入重复的key ,count结果而言 要么是0,要么是1
//multimap 允许相同key重复插入
int num = m.count(3);
cout << "num = " << num <<endl;
}
/*map容器排序
*map容器默认排序规则为 按照key值进行 从小到大排序 掌握如何改变排序规则
主要技术点:
*利用仿函数,可以改变排序规则
*/
class Mycompare_sort {
public:
bool operator()(int v1, int v2)const //C3848 加const
{
//降序
return v1 > v2;
}
};
void test_map_sort_01()
{
map<int, int ,Mycompare_sort>m;
m.insert(pair<int, int>(1, 10));
m.insert(pair<int, int>(2, 20));
m.insert(pair<int, int>(3, 30));
m.insert(pair<int, int>(4, 40));
m.insert(pair<int, int>(5, 50));
for (map<int, int, Mycompare_sort>::iterator it = m.begin(); it != m.end(); it++)
{
cout<< "key = " << it->first << " value = "<< it->second <<endl;
}
}
int main()
{
//cout<< <<endl;
test_map_sort_01();
return 0;
}
C++系统学习(STL初识容器2)
于 2022-02-26 17:30:06 首次发布