栈是限定仅在表尾进行插入(入栈、压栈)和删除(出栈、弹栈)惭怍的线性表,遵循先进后出规则。
栈的抽象数据类型
ADT 栈(stack)
Data
同线性表
Operation
InitStack(*S) 初始化操作,创建一个空栈
DestroyStack(*S) 若栈存在,则摧毁它
ClearStrack(*S) 清除栈中数据
StackEmpty(*S) 判断栈是否为空
GetTop(S,*e) 若栈存在并且非空,用e返回S的栈顶元素
Push(*S,e) 若栈S存在并且未溢出,插入新元素e到栈S中并成为栈顶元素
Pop(*S,*e) 若栈S存在并且非空,删除栈S的栈顶元素,并用e返回其值
StackLength(S) 返回栈S的元素个数
栈的顺序存储结构及实现
栈的结构定义:
typedef struct{
int data[MAXSIZE]; //栈的大小
int top; //栈顶指针
}SqStack;
进栈操作:
Status Push(SqStack *S,int e){
if(S ->top==MAXSIZE-1)return -1; //检查溢出
S ->top++;
S ->data[S ->top] = e; //插入元素e
return OK;
}
出栈操作
Status Pop(SqStack *S,int *e){
if(S ->top==-1) return ERROR; //检查空栈
*e = S ->data[S ->top]; //将要删除的元素赋给e
S ->top--; //栈顶减一
return OK;
}
栈的链式存储结构及实现
栈的结构
typedef struct StackNode{
int data;
struct StackNode *next;
}StackNode,*LinkStackPtr;
typedef strcut LinkStack{
LinkStackPtr top;
int count;
}LinkStack;
进栈操作
Status Push(LinkStack *S,int e){
LinkStackPtr s = (LinkStackPtr)malloc(sizeof(StackNode));
s ->data = e;
s ->next = S ->top; //把当前栈顶元素赋值给新的元素节点的直接后继
S ->top = s; //栈顶指针指向新的结点
S ->count++;
return OK;
}
出栈操作
Status Pop(LinkStack *S,int *e){
LinkStackPtr p; //p的存在是为了释放弹出结点
if(StackEmpty(*S))return ERROR;
*e = S ->top ->data;
p = S ->top;
S ->top = S ->top ->next;
free(p);
S ->count--;
return OK;
}
栈的作用
栈的应用--递归
斐波那契数列为 1, 1, 2, 3,..,,F(N)。
F(N) = F(N-1) + F(N-2) (N>=3)
递归代码实现:
int Fbi(int n){
if(n<=2)return n==0? 0:1;
return Fbi(n-1)+Fbi(n-2); //递归实现
}
进入函数的顺序为 F(n)->F(n-1)->F(n-2)->..->F(1);
运行到F(1)时遇到临界条件,则退出函数,其顺序为F(1)-> F(2) -> F(3) -> ...-> F(n);
实行的是先进后出规则。
栈顶应用--四则运算表达式
计算四则运算表达式的方法:
(1)标准四则运算表达式(中缀表达式)转换成后缀表达式(栈用来进出运算符号)。
代码实现:
class Solution{
public:
vector<string> ToRPN(vactor<string> &infix){
stack<string> str; //存放运算符的栈
vector<string> rpn; //存放后缀表达式
for(auto c:infix)
{
if(c=="*"||c=="/"||c=="(")
{
str.push(c);
}
else if(c=="+"||c=="-")
{
while(str.top()!="(" && str.top()) //遇到优先级高的,将栈中符号取出
{ rpn.push(str.top());
str.pop();
}
str.push(c);
}
else if(c==")") //遇到右括号,依次取出栈顶元素知道"("出现
{
while(str.top!="(" &&str.top())
{ rpn.push(str.top());
str.pop();
}
str.pop();
}
else //数字
{
rpn.push(c);
}
}
return rpn;
}
}
(2)后缀表达式进行运算得到结果(栈用来进出运算数字)。
代码实现:
class Solution{
public:
int evalRPN(vector<string> &tokens){
stack<int> numbers;
for(auto c:tokens){
if(c=="+"||c=="-"||c=="*"||c=='/')
{
if(store.size()<2)return 0;
int after = numbers.top(); numbers.pop();
int before = numbers.top();numbners.pop();
if(c=="+")
numbers.push(before+after);
if(c=="-")
numbers.push(before-after);
if(c=="*")
number.push(before*after);
if(c=="/")
number.push(before/after);
}
else
{
numbers.push(stoi(c)) //stoi()将字符转化数字
}
}
return numbers.top();
}
}