一、stack容器-基本概念
1.stack是一种先进后出(First in Last out,FILO)的数据结构,它有一个出口。
栈顶元素有push()、pop()、top()等方法。
栈中只有顶端的元素才可以被外界使用,所以栈不允许有遍历操作。
栈可以判断容器为空empty(),栈可以返回元素的个数size()。
2.栈中只有顶端元素才可以被外界使用,所以栈不允许有遍历操作。
栈中进入数据成为入栈(push),栈中弹出元素数据称为出栈(pop)
3.stack常用接口:
功能描述:栈容器常用的对外接口
cpp
//构造函数:
stack<T> stk;//stack采用模版类实现,stack对象的默认构造形式
stack(const stack &stk);//拷贝构造函数
//赋值操作
stack& operator(const stack &stk);//重载等号操作符
//数据存取
push(elem);//向栈顶添加元素
pop();//从栈顶移除第一个元素
top();//返回栈顶元素
//大小操作
empty();//判断栈是否为空
size();//返回栈的大小
4.代码实现
cpp
#include<iostream>
#include<stack>
#include<algorithm>//标准算法的头文件
using namespace std;
void test(){
//特点:符合先进后出
stack<int>s;
//入栈
s.push(10);
s.push(20);
s.push(30);
s.push(40);
cout<<"before stack pop,stack size is:"<<s.size()<<endl;
//只要栈不为空,查看栈顶,并且执行出栈操作
while(!s.empty())
{
//查看栈顶
cout<<"stack top element:"<<s.top()<<endl;
//出栈
s.pop();
}
cout<<"After stack pop,stack size is:"<<s.size()<<endl;
}
int main(){
test();
}
cpp
//输出
before stack pop,stack size is:4
stack top element:40
stack top element:30
stack top element:20
stack top element:10
After stack pop,stack size is:0
二、queue容器
1.概念:queue容器是一种先进先出(First in first out,FIFO)的数据结构,它有两个出口。
队列容器允许从一端新增数据,从另一端移除数据。
队列中只有队头和队尾元素可以被外界使用,因此队列不允许有遍历操作。
队列中进数据称为--入队(push)
队列中出数据成为---出队(pop)
队头(front)可以出队pop。
队尾(back)可以入队push。
2.函数原型
cpp
//构造函数
queue<T> que;//queue采用模版类实现,queue对象的默认构造形式
queue(const queue&que);//拷贝构造函数
//赋值操作
queue operator=(const queue&que);//重载等号操作符
//数据存取
push(elem);//队尾添加元素
pop();//从队头移除第一个元素
back();//返回最后一个元素
front();//返回第一个元素
//大小操作
empty();//判断堆栈是否为空
size();//返回栈的大小
3.代码实现
cpp
//队列容器--queue
#include<iostream>
#include<queue>
#include<algorithm>//标准算法的头文件
using namespace std;
//队列queue
class Person{
public:
Person(string name,int age)
{
this->m_Name=name;
this->m_Age=age;
}
string m_Name;
int m_Age;
};
void test(){
//创建队列
queue<Person> q;
//准备数据,初始化
Person p1("唐僧",30);
Person p2("孙悟空",20);
Person p3("猪八戒",10);
Person p4("沙和尚",50);
//入队
q.push(p1);
q.push(p2);
q.push(p3);
q.push(p4);
cout<<"queue size is:"<<q.size()<<endl;
//判断只要队列不为空,查看队头,查看队尾,做出队的操作
while(!q.empty())
{
//查看队头元素
cout<<"queue head element name:"<<q.front().m_Name<<"queue head element age:"<<q.front().m_Age<<endl;
//查看队尾元素
cout<<"queue tail element name:"<<q.back().m_Name<<"queue tail element age:"<<q.back().m_Age<<endl;
//出队
q.pop();
}
}
int main()## 标题{
test();
}
cpp
//输出
queue size is:4
queue head element name:唐僧queue head element age:30
queue tail element name:沙和尚queue tail element age:50
queue head element name:孙悟空queue head element age:20
queue tail element name:沙和尚queue tail element age:50
queue head element name:猪八戒queue head element age:10
queue tail element name:沙和尚queue tail element age:50
queue head element name:沙和尚queue head element age:50
queue tail element name:沙和尚queue tail element age:50
总结:
入队--push
出队--pop
返回队头元素---front
返回队尾元素---back
判断队伍是不是为空--empty
返回队列大小--size。
三、list基本容器--list基本概念
1.功能:将数据进行链式存储。
链表(list)是一种无力存储单元上非连续的存储结构,数据元素的逻辑顺序是通过链表中的指针链接实现的。
2.链表的组成:链表是由一系列节点组成。
3.节点的组成:一个是存储数据元素的数据域,另一个是存储下一个节点地址的指针域。
4.STL中的链表是一个双向循环链表。
所以list可以在头部进行插入和删除,比如push_front(),pop_front()。也可以在尾部进行插入和删除,比如push_back(),pop_back().
5.链表的优点:可以对任意位置进行快速插入和删除元素。
链表的缺点:链表对容器的遍历速度,没有数组快。链表占用的空间比数组占用的空间大。
6.由于链表的存储方式不是连续的内存空间,所以链表的list中的迭代器只支持前移和后移,属于双向迭代器。
list优点:
(1)采用动态存储分配,不会造成内存浪费和溢出。
(2)链表执行插入和删除操作十分方便,修改指针即可,不需要移动大量元素。
list缺点:
(1)链表灵活,但是空间(指针域)和时间(遍历)额外耗费较大。
List有个重要性质,插入操作和删除操作都不会造成原有list迭代器的失效,这在vector是不成立的。
总结:STL中的list和vector是2个常用的容器,各有优缺点。
四、list容器--构造函数
1.功能:创建list容器
2.函数原型:
cpp
//list采用模版类实现,对象的默认构造形式
list<T> list;
//构造函数将[beg,end)区间中的元素拷贝给本身
list(beg,end);
//构造函数将n个elem拷贝给本身
list(n,elem);
//拷贝构造函数
list(const list &list);
3.代码实现
cpp
// list容器
#include<iostream>
#include<list>
#include<algorithm>//标准算法的头文件
using namespace std;
void printList(const list<int>&L)
{
for(list<int>::const_iterator it=L.begin();it!=L.end();it++)
{
cout<<*it<<" ";
}
cout<<endl;
}
void test(){
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(L2);
printList(L3);
//n个elem
list<int>L4(10,10000);
printList(L4);
}
int main(){
test();
return 0;
}
cpp
//输出
10 20 30 40
10 20 30 40
10 20 30 40
10000 10000 10000 10000 10000 10000 10000 10000 10000 10000
五、list容器--赋值和交换
1.功能描述:给list容器进行复制,以及交换list容器
2.函数原型
cpp
//将[beg,end)区间中的数据拷贝给本身
assign(beg,end);
//讲n个elem拷贝赋值给本身
assign(n,elem);
//重载等号操作符
list& operator=(const list &list);
//将list与本身元素互换
swap(list);
3.代码实现
cpp
// list容器赋值和交换
#include<iostream>
#include<list>
#include<algorithm>//标准算法的头文件
using namespace std;
void printList(const list<int>&L)
{
for(list<int>::const_iterator it=L.begin();it!=L.end();it++)
{
cout<<*it<<" ";
}
cout<<endl;
}
//赋值
void test(){
list<int>L1;
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
L1.push_back(40);
printList(L1);
//等号赋值
list<int>L2;
L2=L1;
printList(L2);
//区间赋值
list<int>L3;
L3.assign(L2.begin(),L2.end());
printList(L3);
list<int>L4;
L4.assign(10,100);
printList(L4);
}
//交换
void test02()
{
list<int> L1;
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
L1.push_back(40);
list<int> L2;
L2.assign(10,100);
cout<<"Before swap:"<<endl;
printList(L1);
printList(L2);
L1.swap(L2);
cout<<"After swap:"<<endl;
printList(L1);
printList(L2);
}
int main(){
test02();
}
cpp
//输出
Before swap:
10 20 30 40
100 100 100 100 100 100 100 100 100 100
After swap:
100 100 100 100 100 100 100 100 100 100
10 20 30 40
五、list容器--赋值和交换
1.功能描述:给list容器进行赋值,交换list容器。
2.函数原型
cpp
assign(beg,end);//讲[beg,end)区间中的数据拷贝赋值给本身。
assign(n,elem);//将n个elem拷贝赋值给本身。
list & opearator=(const list & list);//重载等号操作符
swap(list);//将list与本身的元素互换
3.代码实现
cpp
// list容器赋值和交换
#include<iostream>
#include<list>
#include<algorithm>//标准算法的头文件
using namespace std;
void printList(const list<int>& L){
for(list<int>::const_iterator it=L.begin();it!=L.end();it++)
{
cout<<*it<<" ";
}
cout<<endl;
}
void test(){
list<int> L1;
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
cout<<"L1 element:"<<endl;
printList(L1);
list<int>L2;
L2=L1;//采用操作符重载的方式,赋值
cout<<"L2 element:"<<endl;
printList(L2);
//区间的方式赋值
list<int> L3;
L3.assign(L2.begin(),L2.end());
cout<<"L3 element:"<<endl;
printList(L3);
//n个elem
list<int> L4;
L4.assign(10,100);
cout<<"L4 element:"<<endl;
printList(L4);
}
//交换
void test02(){
list<int>L1;
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
L1.push_back(40);
list<int>L2;
L2.assign(10,100);
cout<<"before exchanging:"<<endl;
printList(L1);
printList(L2);
L1.swap(L2);
cout<<"After exchanging:"<<endl;
printList(L1);
printList(L2);
}
int main(){
test();
test02();
}
cpp
//输出
L1 element:
10 20 30
L2 element:
10 20 30
L3 element:
10 20 30
L4 element:
100 100 100 100 100 100 100 100 100 100
before exchanging:
10 20 30 40
100 100 100 100 100 100 100 100 100 100
After exchanging:
100 100 100 100 100 100 100 100 100 100
10 20 30 40
五、list容器--大小操作
1.功能描述:
对list容器的大小进行操作。
2.函数原型:
cpp
size();//返回容器中的元素个数
empty();//判断容器是否为空
resize(num);//重新指定容器的长度为num,若容器变长,则以默认值填充新位置。//如果容器变短,则末尾超出容器长度的元素被删除。
resize(num,elem);//重新指定容器的长度为num,若容器变长,则以elem值填充新位置。//如果容器变短,则末尾超出容器长度的元素被删除。
3.代码实现:
cpp
// list容器大小操作
#include<iostream>
#include<list>
#include<algorithm>//标准算法的头文件
using namespace std;
void printList(const list<int>& L){
for(list<int>::const_iterator it=L.begin();it!=L.end();it++)
{
cout<<*it<<" ";
}
cout<<endl;
}
void test(){
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 is not empty:"<<endl;
cout<<"L1 size:"<<L1.size()<<endl;
}else{
cout<<"L1 is empty:"<<endl;
}
//重新指定容器大小
//L1.resize(10);
printList(L1);
//重新指定容器大小
L1.resize(10,100);
printList(L1);
//重新指定容器大小
L1.resize(2);
printList(L1);
}
int main(){
test();
}
cpp
//输出
10 20 30 40
L1 is not empty:
L1 size:4
10 20 30 40
10 20 30 40 100 100 100 100 100 100
10 20
五、list容器--插入和删除操作
1.功能描述:对list容器进行数据的插入和删除
2.函数原型
cpp
push_back(elem);//在容器尾部加入一个元素
pop_back();//删除容器中最后一个元素
push_front(elem);//在容器开头插入一个元素
pop_front();//从容器开头移除第一个元素
insert(pos,elem);//在pos位置插入n个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值匹配的元素。
3.代码实现
cpp
// list插入和删除
#include<iostream>
#include<list>
#include<algorithm>//标准算法的头文件
using namespace std;
void printList(const list<int>& L){
for(list<int>::const_iterator it=L.begin();it!=L.end();it++)
{
cout<<*it<<" ";
}
cout<<endl;
}
void test(){
list<int>L;
//尾插
L.push_back(10);
L.push_back(20);
L.push_back(30);
//头插
L.push_front(100);
L.push_front(200);
L.push_front(300);
//300 200 100 10 20 30
printList(L);
//尾删
L.pop_back();//300 200 100 10 20
printList(L);
//insert插入区间
L.insert(L.begin(),1000);
printList(L);
}
int main(){
test();
}
cpp
//输出
300 200 100 10 20 30
300 200 100 10 20
1000 300 200 100 10 20
使用迭代器,使得插入的位置可以是以任意步长
cpp
// list插入和删除
#include<iostream>
#include<list>
#include<algorithm>//标准算法的头文件
using namespace std;
void printList(const list<int>& L){
for(list<int>::const_iterator it=L.begin();it!=L.end();it++)
{
cout<<*it<<" ";
}
cout<<endl;
}
void test(){
list<int>L;
//尾插
L.push_back(10);
L.push_back(20);
L.push_back(30);
//头插
L.push_front(100);
L.push_front(200);
L.push_front(300);
//300 200 100 10 20 30
printList(L);
//尾删
L.pop_back();//300 200 100 10 20
printList(L);
//insert插入区间
// L.insert(L.begin(),1000);
// printList(L);
list<int>::iterator it=L.begin();
L.insert(++it,985);
printList(L);
}
int main(){
test();
}
cpp
//输出
300 200 100 10 20 30
300 200 100 10 20
300 985 200 100 10 20
删除第二个元素
cpp
// list插入和删除
#include<iostream>
#include<list>
#include<algorithm>//标准算法的头文件
using namespace std;
void printList(const list<int>& L){
for(list<int>::const_iterator it=L.begin();it!=L.end();it++)
{
cout<<*it<<" ";
}
cout<<endl;
}
void test(){
list<int>L;
//尾插
L.push_back(10);
L.push_back(20);
L.push_back(30);
//头插
L.push_front(100);
L.push_front(200);
L.push_front(300);
//300 200 100 10 20 30
printList(L);
//尾删
L.pop_back();//300 200 100 10 20
printList(L);
//insert插入区间
// L.insert(L.begin(),1000);
// printList(L);
list<int>::iterator it=L.begin();
L.insert(++it,985);
printList(L);
//删除
it=L.begin();
L.erase(++it);
printList(L);
}
int main(){
test();
}
cpp
//输出
300 200 100 10 20 30
300 200 100 10 20
300 985 200 100 10 20
300 200 100 10 20
remove(elem):删除容器中所有与elem匹配的元素,不管多少个elem
cpp
// list插入和删除
#include<iostream>
#include<list>
#include<algorithm>//标准算法的头文件
using namespace std;
void printList(const list<int>& L){
for(list<int>::const_iterator it=L.begin();it!=L.end();it++)
{
cout<<*it<<" ";
}
cout<<endl;
}
void test(){
list<int>L;
//尾插
L.push_back(10);
L.push_back(20);
L.push_back(30);
//头插
L.push_front(100);
L.push_front(200);
L.push_front(300);
//300 200 100 10 20 30
printList(L);
//尾删
L.pop_back();//300 200 100 10 20
printList(L);
//insert插入区间
// L.insert(L.begin(),1000);
// printList(L);
list<int>::iterator it=L.begin();
L.insert(++it,985);
printList(L);
//删除
it=L.begin();
L.erase(++it);
printList(L);
//删除容器中所有1000
L.push_back(1000);
L.push_back(1000);
L.push_back(1000);
L.push_back(1000);
printList(L);
L.remove(1000);
printList(L);
//容器中所有的元素清空
L.clear();
printList(L);
}
int main(){
test();
}
cpp
//输出
300 200 100 10 20 30
300 200 100 10 20
300 985 200 100 10 20
300 200 100 10 20
300 200 100 10 20 1000 1000 1000 1000
300 200 100 10 20
六、list容器-数据存取
list容器去取第一个元素和最后一个元素
cpp
// list数据存取
#include<iostream>
#include<list>
#include<algorithm>//标准算法的头文件
using namespace std;
void test(){
list<int>L;
//尾插
L.push_back(10);
L.push_back(20);
L.push_back(30);
L.push_back(40);
//L1[0]不可以用[]访问list容器中的元素
//L1.at(0)不可以用at方式访问list容器中的元素
//list本身是链表,不是用线性空间存储数据,迭代器也是不支持随机访问
cout<<"The first element:"<<L.front()<<endl;
cout<<"The last element:"<<L.back()<<endl;
//验证迭代器是不支持随机访问的
list<int>::iterator it=L.begin();
it++;
it--;//++和--不报错,说明是双向迭代器。
//不能是it+1,不能说it+2,不支持随机访问
}
int main(){
test();
}
cpp
//输出
The first element:10
The last element:40
七、list容器的反转和排序
cpp
// list反转和排序
#include<iostream>
#include<list>
#include<algorithm>//标准算法的头文件
using namespace std;
void printList(const list<int>& L){
for(list<int>::const_iterator it=L.begin();it!=L.end();it++)
{
cout<<*it<<" ";
}
cout<<endl;
}
void test(){
list<int>L;
//尾插
L.push_back(10);
L.push_back(20);
L.push_back(30);
L.push_back(40);
cout<<"before reverse:"<<endl;
printList(L);
L.reverse();
cout<<"After reverse:"<<endl;
printList(L);
}
void test02(){
list<int>L;
//尾插
L.push_back(100);
L.push_back(200);
L.push_back(300);
L.push_back(400);
L.push_back(40);
cout<<"before sort:"<<endl;
printList(L);
L.sort();
cout<<"After sort:"<<endl;
printList(L);
}
int main(){
test();
test02();
}
cpp
//输出
before reverse:
10 20 30 40
After reverse:
40 30 20 10
before sort:
100 200 300 400 40
After sort:
40 100 200 300 400
排序,包括升序和降序
cpp
// list反转和排序
#include<iostream>
#include<list>
#include<algorithm>//标准算法的头文件
using namespace std;
void printList(const list<int>& L){
for(list<int>::const_iterator it=L.begin();it!=L.end();it++)
{
cout<<*it<<" ";
}
cout<<endl;
}
void test(){
list<int>L;
//尾插
L.push_back(10);
L.push_back(20);
L.push_back(30);
L.push_back(40);
cout<<"before reverse:"<<endl;
printList(L);
L.reverse();
cout<<"After reverse:"<<endl;
printList(L);
}
//降序排序
bool myCompare(int v1,int v2){
//降序,第一个数>第二个数
return v1>v2;
}
void test02(){
list<int>L;
//尾插
L.push_back(100);
L.push_back(200);
L.push_back(300);
L.push_back(400);
L.push_back(40);
cout<<"before sort:"<<endl;
printList(L);
L.sort();//默认的排序规则,从小到大。
cout<<"After sort:"<<endl;
printList(L);
//所有不支持随机访问的容器,都不能用标准的算法,全局标准函数L.sort(L1.begin(),L1.end())
L.sort(myCompare);//降序,从大到小。
printList(L);
}
int main(){
test();
test02();
}
cpp
//输出
before reverse:
10 20 30 40
After reverse:
40 30 20 10
before sort:
100 200 300 400 40
After sort:
40 100 200 300 400
400 300 200 100 40
八、排序案例
1.案例描述:将Person自定义数据类型进行排序,Person总属性有姓名、年龄、身高。
2.排序规则:按照年龄升序排序,如果年龄相同按照身高进行j降序排序
3.代码实现:
cpp
// list排序案例
#include<iostream>
#include<list>
#include<algorithm>//标准算法的头文件
using namespace std;
class Person{
public:
Person(string name,int age,int height){
this->m_Name=name;
this->m_Age=age;
this->m_Height=height;
}
public:
string m_Name;
int m_Age;
int m_Height;
};
bool myCompare(Person&p1,Person&p2){
return p1.m_Age<p2.m_Age;
}
bool specCompare(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<Person> L;//创建容器
//准备数据
Person p1("LL",49,160);
Person p2("kk",29,170);
Person p3("MM",19,172);
Person p4("PP",39,175);
Person p5("QQ",39,178);
//插入数据
L.push_back(p1);
L.push_back(p2);
L.push_back(p3);
L.push_back(p4);
L.push_back(p5);
for(list<Person>::iterator it=L.begin();it!=L.end();it++)
{
cout<<"Name:"<<(*it).m_Name<<",Age:"<<(*it).m_Age<<",Height:"<<(*it).m_Height<<endl;
}
cout<<"After sorting ,we up sort by age:"<<endl;
//要传入排序规则,或者反函数
L.sort(myCompare);
for(list<Person>::iterator it=L.begin();it!=L.end();it++)
{
cout<<"Name:"<<(*it).m_Name<<",Age:"<<(*it).m_Age<<",Height:"<<(*it).m_Height<<endl;
}
cout<<"If two person have the same age,we down sort by height :"<<endl;
L.sort(specCompare);
for(list<Person>::iterator it=L.begin();it!=L.end();it++)
{
cout<<"Name:"<<(*it).m_Name<<",Age:"<<(*it).m_Age<<",Height:"<<(*it).m_Height<<endl;
}
}
int main(){
test();
}
cpp
//输出
Name:LL,Age:49,Height:160
Name:kk,Age:29,Height:170
Name:MM,Age:19,Height:172
Name:PP,Age:39,Height:175
Name:QQ,Age:39,Height:178
After sorting ,we up sort by age:
Name:MM,Age:19,Height:172
Name:kk,Age:29,Height:170
Name:PP,Age:39,Height:175
Name:QQ,Age:39,Height:178
Name:LL,Age:49,Height:160
If two person have the same age,we down sort by height :
Name:MM,Age:19,Height:172
Name:kk,Age:29,Height:170
Name:QQ,Age:39,Height:178
Name:PP,Age:39,Height:175
Name:LL,Age:49,Height:160