一、适配器
适配器是一种设计模式,能够将一个类的接口转换成客户希望的另外一个接口,从而使原本接口不匹配而无法在一起工作的两个类能够在一起工作。比如对于笔记本来说,电源额定电压是220V,而美国电压是110V,为了能在美国使用,必须要用变压器转换电压以匹配美国电压,那么这个变压器就是个适配器。
容器适配器是一个封装了序列容器的类模板,它在一般序列容器的基础上提供了一些不同的功能。它可以通过适配容器现有的接口来提供不同的功能,所以叫作适配器类。
虽然stack和queue中也可以存放元素,但在STL中并没有将其划分在容器的行列,而是将其称为容器适配器,这是因为stack和队列只是对其他容器的接口进行了包装,STL中stack和queue默认使用deque。
二、栈
1.栈的性质
(1)stack是一种容器适配器,专门用在具有后进先出操作的上下文环境中,其删除只能从容器的一端进行元素的插入与提取操作。
(2) stack是作为容器适配器被实现的,容器适配器即是对特定类封装将其作为底层的容器,并提供一组特定的成员函数来访问其元素,将特定类作为其底层,元素从特定容器的尾部(即栈顶)被压入和弹出。
(3)stack的底层容器可以是任何标准的容器类模板或者一些其他特定的容器类,这些容器类应该支持以下操作:
empty:判空操作
back:获取尾部元素操作
push_back:尾部插入元素操作
pop_back:尾部删除元素操作
(4) 标准容器vector、deque、list均符合这些需求,默认情况下,如果没有为stack指定特定的底层容器, 默认情况下使用deque。
2.栈类
(1)栈的构造
构造一个栈
explicit stack (const container_type& ctnr = container_type());//构造一个栈的容器适配器对象
构造一个栈st1:
stack<int> st1;//构造一个空栈st1
(2)empty( )
判断栈是否为空
bool empty() const;//判断栈是否为空
判断st1是否为空:
cout << st1.empty() << endl;
(3)push( )
从栈顶插入元素
void push (const value_type& val);//向栈顶插入元素值为val的元素
向栈顶插入值分别为1,2,3,4的4个元素
st1.push(1);
st1.push(2);
st1.push(3);
st1.push(4);
F10监视可以看到 st1有4个元素:
(4)pop( )
从栈顶删除元素
void pop();
st1.pop();//删除st1栈顶元素4
执行pop后,st1只有3个元素,4被删除了
(5)top( )
返回栈顶元素引用
value_type& top();
const value_type& top() const;
修改栈顶元素,现在栈顶元素是3:
st1.top() += 20;
执行后变成了23:
(6)size( )
求栈的元素个数:
size_type size() const;
求st1栈的元素个数:
cout << st1.size() << endl;
三、栈的模拟实现
栈作为容器适配器, 不像string、vector、list等是完整的容器类,栈不是完整的容器类,而是提供特定接口的类,相当于在完整容器外面包装了一层,比如使用vector实现栈,就可以借助vector的操作来实现栈的操作。
栈的构造函数、拷贝构造函数、赋值运算符载函数、析构函数不需要写,会调用vector自己的默认构造函数、拷贝构造函数、赋值运算符重载函数、析构函数。
016-stack.h
#pragma once
#include<iostream>
#include<vector>
namespace delia
{
//容器适配器
template<class T,class Container = std::vector<T>>//这里指定底层容器为vector,而底层也可以不用vector实现,也可以用list实现
class stack
{
public:
//栈的插入
void push(const T& x)
{
_con.push_back(x);
}
//栈的删除
void pop()
{
_con.pop_back();
}
//返回栈顶元素
T top()
{
return _con.back();
}
//求栈中元素的个数
size_t size()
{
return _con.size();
}
//判断栈是否为空
bool empty()
{
return _con.empty();
}
private:
Container _con;
};
}
016-test.cpp
#include<iostream>
using std::cout;
using std::endl;
#include "016-stack.h"
void test_stack()
{
delia::stack<int> st;
st.push(1);
st.push(2);
st.push(3);
st.push(4);
while (!st.empty())
{
cout << st.top() << " ";//打印栈顶元素
st.pop();//弹出栈顶元素
}
cout << endl;
}
int main()
{
test_stack();
return 0;
}
打印结果:
假如底层不想用vector实现,可以用list实现,只需要修改第3行和第8行:
#pragma once
#include<iostream>
#include<list>
namespace delia
{
//容器适配器
template<class T,class Container = std::list<T>>//这里指定底层容器为vector,而底层也可以不用vector实现,也可以用list实现
class stack
{
public:
//栈的插入
void push(const T& x)
{
_con.push_back(x);
}
//栈的删除
void pop()
{
_con.pop_back();
}
//返回栈顶元素
T top()
{
return _con.back();
}
//求栈中元素的个数
size_t size()
{
return _con.size();
}
//判断栈是否为空
bool empty()
{
return _con.empty();
}
private:
Container _con;
};
}