模拟实现栈的基本功能,并用以检查括号匹配问题。
#include<iostream>
using namespace std;
#include<assert.h>
template<class T>
class Stack
{
public:
Stack()
:_ptr(NULL)
,_size(0)
,_capacity(0)
{
}
~Stack()
{
if (_size!=0)
{
delete[]_ptr;
_ptr=NULL;
_size=0;
_capacity=0;
}
}
Stack(const Stack& s)
:_ptr(new T[s._capacity-1])
{
swap(_ptr,s._ptr);
_size=s._size;
_capacity=s._capacity;
}
void Push(const T& x)
{
if (_size==_capacity)
{
Check();
}
_ptr[_size]=x;
_size++;
}
void Pop()
{
if (_size>0)
{
_size--;
}
}
T& Top()
{
return _ptr[_size-1];
}
bool Empty()
{
return _size==0;
}
size_t Size()
{
return _size;
}
void Check()
{
if (_capacity==_size)
{
size_t newcapa=_capacity*2+2;
T* tmp=new T[newcapa];
assert(tmp);
size_t i=0;
while (i<_size)
{
tmp[i]=_ptr[i];
}
delete[]_ptr;
_ptr=tmp;
}
}
void Display()
{
if (_size==0)
{
cout<<"NULL";
}
for (size_t i=0; i<_size; i++)
{
cout<<_ptr[i]<<" ";
}
cout<<endl;
}
private:
T* _ptr;
size_t _size;
size_t _capacity;
};
void test()
{
Stack<int> s;
s.Push(1);
s.Push(2);
s.Push(3);
s.Push(4);
s.Display();
cout<<"top="<<s.Top()<<endl;
s.Pop();
s.Pop();
s.Pop();
s.Pop();
s.Display();
}
bool Bracket(Stack<int>& s,FILE* pf)
{
while (getc(pf)!=EOF)
{
char ch=getc(pf);
if (ch=='{')
{
s.Push(1);
}
else if(ch=='}')
{
s.Pop();
}
}
if (s.Empty())
{
return true;
}
return false;
}
int main()
{
Stack<int> s;
FILE* pf=fopen("test.c","r");
assert(pf);
if (Bracket(s,pf))
{
cout<<"匹配"<<endl;
}
else
cout<<"不匹配"<<endl;
return 0;
}
检查括号匹配的目标文件内容如下:
检查结果:
关于容器适配器
适配器其实就是一个接口转换装置,是得我们能用特定的方法去操作一些我们本来无法操作的东西。举一个例子,比如你的一个设备支持串口线,而你的电脑支持的是usb口,这时候,我们没有必要重新买一个支持usb的设备,只需要一根串口转usb口的小玩意,让你的设备能够连接到usb插口上,而它就是适配器。
那么C++中的容器适配器是干什么的呢?可以做一个类比,我们已有的容器(比如vector、list、deque)就是设备,这个设备支持的操作很多,比如插入,删除,迭代器访问等等。而我们希望这个容器表现出来的是栈的样子:先进后出,入栈出栈等等,此时,我们没有必要重新动手写一个新的数据结构,而是把原来的容器重新封装一下,改变它的接口,就能把它当做栈使用了。
理解了什么是适配器以后,其实问题就很简单的。C++中定义了3种容器适配器,它们让容器提供的接口变成了我们常用的的3种数据结构:栈(先进后出)队列(先进先出)和优先级队列(按照优先级(“<”号)排序,而不是按照到来的顺序排序)。
至于具体是怎么变的,我们可以先了解一个大概:默认情况下,栈和队列都是基于deque实现的,而优先级队列则是基于vector实现的。当然,我们也可以指定自己的实现方式。但是由于数据结构的关系,我们也不能胡乱指定。栈的特点是后进先出,所以它关联的基本容器可以是任意一种顺序容器,因为这些容器类型结构都可以提供栈的操作有求,它们都提供了push_back、pop_back和back操作。队列queue的特点是先进先出,适配器要求其关联的基础容器必须提供pop_front操作,因此其不能建立在vector容器上;对于优先级队列,由于它要求支持随机访问的功能,所以可以建立在vector或者deque上,不能建立在list上。