重点:栈具有“后进先出”的特点
栈的定义:栈是一种操作受限的(先进后出)线性结构,只允许从一端进出,这是栈的特点,一般数据进出的一端我们称为栈顶,另一端则为栈底,栈的基本操作包含进栈、出栈、判空、取栈顶元素等等。
栈的具体应用:
- 最小栈(后续更新)
- 有效括号(后续更新)
- 栈实现队列(后续更新)
- 栈求表达式(后续更新)
顺序栈的学习与实现:
- 定义栈结构:
#include<iostream>
using namespace std;
#define MaxSize 128
typedef int ElemType; //typedf定义别名 ElemType 表示数据类型 此时为 int
typedef struct _SqStack {
ElemType *base; //栈底指针 可理解为new一个数组首地址,详情可以搜索指针与数组的关系
ElemType *top; //栈顶指针 为后续的出栈入栈做准备 具体实现是移动top指针
}SqStack;
- 栈的初始化:
//初始化栈 这里定义的是一个bool函数,因为它可能初始化失败,主要是分配空间失败
bool initStack(SqStack &sq) {
sq.base = new ElemType[MaxSize];//为顺序栈分配最大容量空间
if (!sq.base) return false;//分配空间失败
sq.top = sq.base;//top初始为base,空栈; base此时可理解为数组存储的首地址
return true;
}
- 判断栈空栈满条件:
//栈空判断
bool isEmpty(SqStack &sq) {
if (sq.base == sq.top)return true;//栈顶==栈底 表示栈内无元素
return false;
}
//栈满判断
bool isFull(SqStack &sq) {
if ((sq.top - sq.base) == MaxSize) { //Maxsize为前面定义结构时 分配的最大容量
return true; //栈顶的指针减去栈底==栈内元素个数
}
return false;
}
- 入栈操作:
//入栈
bool PushStack(SqStack &sq,ElemType e) {//插入新元素e为栈顶元素
if (isFull(sq))return false; //判断是否栈满,如果满了插入失败
*(sq.top++) = e; //元素压入栈顶,等价于*sq.top=e;s.top++;
//将插入元素复制到数组中,即入栈
return true;
}
- 出栈操作:
//出栈
bool PopStack(SqStack &sq, ElemType&e) { //ElemType&e 表示 获取出栈的值,即保存出栈的元素
if (isEmpty(sq)) return false; //判断栈是否为空,如果为空,则出栈失败
e = *(--sq.top); //--sq.top 先自减的原因 是因为入栈时top指针指向栈顶元素的后一位
return true;
}
- 获取栈顶元素:
//获取栈顶元素
ElemType GetTop(SqStack &sq) { //ElemType 是自己改名后的数据类型 此时为 int
if (!isEmpty(sq)) {
return *(sq.top - 1);//返回栈顶元素的值,栈顶指针不变
}
else {
return -1;
}
}
//获取栈内元素个数
int GetSize(SqStack &sq) {
return sq.top - sq.base;
}
- 销毁栈,释放内存空间(new 与delete 搭配;malloc 与free 搭配 具体可查帮助c/c++帮助文档)
//销毁栈
void destory(SqStack &sq) {
if (sq.base) {
delete(sq.base);
sq.base = NULL; //初始化栈底指针(养成初始化指针习惯) 避免空指针
sq.top = NULL; //初始化栈顶指针
}
}