好久都没来了,实在是每个星期只有三节或者四节空课,忙死了,不过以后一定不能鸽了,我会坚持的,所以话不多说,我们今天来用代码实现栈,今天写不完的会放到明天
栈的实现
一.栈的定义
上一章,我们学习了线性表,线性表与其他数据结构比如图、树,最大的区别就在于:
线性结构:数据元素之间一对一
树形结构:数据元素之间一对多
图形结构:数据元素之间多对多
而像线性结构这样一对一的线性表,又衍生出来了多种类似但又不一样的数据结构:栈,队列,优先级队列,双端队列
栈其实可以理解为一个空盒子,我们从盒子的开口往里边放书籍,也可以从盒子的开口处往外拿书籍,但是我们却不可以从盒子的底部拿书,这样是不符合常理的,理解了栈大概是什么样之后,我们就来讲栈的规范定义
栈:只允许在表的末端进行插入(放书)和删除(取书)的线性表
允许插入和删除的一端称为栈顶,不允许插入和删除的一端称为栈底,所以它其实和普通线性表最大的区别就在于栈比线性表多了一些规定
二.顺序栈
1.如何用顺序表来实现栈?
首先分析一下一个栈,我们需要定义什么函数才能比较灵活的使用它?
1)构造函数
构造函数总要吧,你需要使用一个栈,就一定得先把栈构造出来吧,把它得一些属性初始化吧,所以第一个:
Stack(int sz);//构造函数 (具体有什么属性待会再讲)
其中,int sz就是可以让你指定买多大的盒子给你装书,就是容量大小
2)新元素进栈函数
有了一个栈(空盒子)之后,元素肯定要进去吧,不然这个盒子用来摆设的?所以第二个:
void Push(T& x); //新元素
其中我们知道添加一个元素之后,添加就是添加了,肯定不需要再有什么返回值,所以返回值为void
其次,由于我们不知道这个添加的元素是一个什么类型,所以我们这里运用了模板,不懂C++模板的小伙伴可以浅看一下模板,其实也很简单,就是由于你不知道这个栈里边究竟放的是int类型数据,还是string类型数据,还是double类型数据,太多了,我不可能每一个都跟你写一样的代码,只是数据类型不同吧,所以就产生了模板,我们一般这样写:
template <class T> //用T来代表一个未知的数据类型
3)栈顶元素出栈,由x返回
放入了元素之后,我又想取出这个元素需要使用它咋办?所以这时候有了第三个:
bool Pop(T& x);
其中,返回值为bool,代表你究竟返回成功没有啊,我叫你取出这个元素,你取出了没有啊?所以用一个返回值为bool类型
其次,我们也可以用一个x来接收这个被取出来的值,但是在标准STL里边,好像一般不会使用一个x去承接我们取出来的这个值,所以其实也无伤大雅
4)没写完的明天再写(我一定会的。。。不是很相信自己orz)
其次,我们还需要分析这个栈里边有什么属性值,也就是说你把这个箱子买回来,就能知道它有什么属性
1)箱子本身----->其实就是一个数组
2)最大容量数----->maxSize
3)书放到哪一个位置了----->栈顶指针
2.如何用代码实现?
#include <iostream>
using namespace std;
//栈的类
template <class T>
class Stack{
public: //好家伙,这里别忘记写public,不然函数就都是私有的了
Stack(int sz); //构造函数
void Push(T& x); //添加新元素
bool Pop(T& x); //栈顶元素出栈
private:
T *elements; //存放栈中元素的栈数组
int top;
int maxSize;
};
template <class T>
// 构造函数
Stack::Stack(int sz){
top=-1; //买回来,一本书没放,指向最底层
maxSize=sz; //最大容量是你自己买的箱子的大小
elements=new T[maxSize]; //你的箱子
}
template <class T>
void Stack::Push(T& x){
//但是我们还需要考虑到如果箱子已经是满的了呢?
if(top==maxSize-1)
overflowProcess(); //溢出处理,明天再讲
top++; //先瞅中了那个位置,再把元素放进去
elements[top]=x;
}
template <class T>
bool Stack::Pop(T& x){
if(top==-1)
return false; //箱子已经空了
x=elements[top];
top--; //先把箱子中那个元素取出来,书放到的位置才会下降
return true;
}