提到栈,首先想到的就是先进后出,就像堆盘子一样,最先放的盘子放在最下面,最先取出的盘子是最后放的在最上面的盘子。
在网上看到有人打了一个比方,觉得很形象,拿来分享一下。
你就想像栈是一个竹筒,一头封死了,一头有开口可以往里面放东西,这样第一个放进去的东西,就只能最后一个倒出来。第二个放进去的,就倒数批二个倒出来。
至于它有什么用:再打个比方,你在洗衣服,洗到一半,你妈叫你去扫地(妈妈的话不能不听),你怕忘了你洗到哪来了(当然现实中不会,这只是假设。),你在纸上写到“洗到第3件了”然后放到哪个竹筒里去。然后你去扫地,扫了一个房间,突然你爸又叫你,说“我下去买盒烟,炉子上的水快开了,开了你帮我把它灌一下”,水烧干了会出事的,当然比扫地重要,于是你又在纸上写到“我扫地扫到了第一个房间”,然后放进竹筒,然后你去处理水,把水的事处理完了,你再从竹筒里倒出第一张纸,看着上面写着“扫到第一间房”,于是你接着扫完后面的房间。再从竹筒里再倒出一张出来,看见上面写到“洗到第3件”于是你接着洗第4件。
当然上面事情比较简单,但是你想想,如果你做事情的时候千头万绪,有1000件事情,而且你又不能知道它们什么时候会发生,你能记得住每件事做到哪来了吗?所以就用上面的竹筒这种方法,遇到事情如果比当前的事情重要,就把它的进度写下来,然后丢进去,处理完了手头的事情,没事做的时候,就倒一个出来接着做。这就是一个栈的应用的模型。
栈的本质还是线性表,只不过它是有特殊的操作要求的线性表。拿到一个栈,我们就只能对其进行入栈、出栈操作,入栈就是把元素放到栈顶(就是往上摞盘子),出栈就是把栈顶的元素取出来(就是把最上面的盘子拿来扔了)。
我们想使用一个栈,就new一个,然后对其进行入栈和出栈操作即可。
Stack<int> * stack = new Stack<int>(6);
stack->push(1);
stack->push(2);
stack->push(3);
stack->push(4);
stack->push(5);
cout<<stack->pop()<<endl;//打印5
cout<<stack->pop()<<endl;//打印4
cout<<stack->pop()<<endl;//打印3
cout<<stack->pop()<<endl;//打印2
cout<<stack->pop()<<endl;//打印1
接着,我们就可以定义Stack
这个类了。可以用数组存储数据,用_top来标志栈顶。如下图:
具体的实现应该是很简单的:
template<typename DataType> class Stack
{
public:
Stack(int capacity = 10)
{
_top = -1;
_capacity = capacity;
_datas = new DataType[capacity];
}
~Stack()
{
delete [] _datas;
}
bool push(DataType data)
{
//如果栈满了,返回false
if (_top + 1 == _capacity )return false;
_top++;
_datas[_top]=data;
return true;
}
DataType pop()
{
//如果栈为空,不能进行出栈操作,则退出
if (_top == -1)exit(1);
return _datas[_top--];
}
private:
DataType* _datas;
int _capacity;//栈的容量
int _top;//标志栈顶
};