265 阅读3分钟

是限定仅在表尾进行插入(入栈、压栈)和删除(出栈、弹栈)惭怍的线性表,遵循先进后出规则。

栈的抽象数据类型

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();   
    }
    
}