【数据结构】栈

栈的定义

栈是限定仅在表尾进行插入和删除操作的线性表。允许插入和删除的一端称为栈顶(top),另一端称为栈底(bottom)。
*后进先出(Last In First Out)*称为LIFO结构。

顺序栈

存储结构

栈的结构定义:

typedef int SELemType;//SELemType根据实际情况而定义。
typedef struct{
   SElemType data[MAXSIZE];
   int top;
}SqStack;

出栈以及进栈

进栈操作push:

//插入元素e为新的栈顶元素
Status Push(SqStack *S,SELemType e){
   if(S->top == MAXSIZE - 1){
      return ERROR;
   }
   S->top++;//栈顶元素加1
   S->data[S->top]=e;//将新插入的元素赋值给栈顶空间
   return OK; 
}

出栈操作pop:

Status Pop(SqStack *S,SELMType *e){
   if(S->top == -1) return ERROR;
   *e = S->data[S->top];//将删除的栈顶元素赋值给e
   S->top--;//栈顶指针减1
   return OK;
}

共享栈

关键思路是:top1和top2是栈1和栈2的栈顶指针,只是在数组两端,向中间靠拢。
栈1空的时候,top1为-1;栈2空的时候,top2为n。
当top1 + 1 == top2时为栈满。
两栈共享空间结构:

typedef struct{
   SElemType data[MAXSIZE];
   int top1;//栈1的栈顶指针
   int top2;//栈2的栈顶指针
}SqDoubleStack;

push方法:

Status Push(SqDoubleStack *S,SElmType e,int stackNumber)
{
   if(S->top1+1 == S->top2) return ERROR;//栈已经满了
   if(stackNumber == 1) S->data[++S->top1]=e;//若栈1有元素进来,则先top1+1后给数组赋值
   else if(stackNumber == 2) S->data[--S->top2]=e;//若栈2有元素进来,则先top2-1后给数组赋值
   return OK
}

pop方法:

Status Pop(SqDoubleStack *S,SElmType e,int stackNumber)
{
   if(stackNumber==1) {
       if(S->top1=-1) return ERROR;//说明栈1位空栈
       *e=S->data[S->top1--];//栈1的栈顶元素出栈
   }
   else if(stackNumber==2){
       if(S->top2=MAXSIZE) return ERROR;//说明栈2位空栈
       *e=S->data[S->top1++];//栈2的栈顶元素出栈
   }
   return OK
}

使用这样的数据结构,通常都是两个栈的空间需求有相反关系的时候(比如买股票)。
针对两个具有相同的数据类型的栈才适用。

链式栈

存储结构

typedef struct StackNode{
   SElemType data;
   srtuct StackNode *next;
}StackNode,*LinkStackPtr;

typedef struct LinkStack{
   LinkStackPtr top;
   int count;
}LinkStack;

出栈以及进栈

进栈push操作:

Status Push(LinkStack *S,SElemType e){
   LinkStackPtr s=(LinkStackPtr)malloc(sizeof(StackNode));
   s->data=e;
   s->next=S->top;//把当前栈顶元素赋值给新节点的直接后继
   S->top=s;//将新的结点s赋值给栈顶指针
   S->count++;
   return OK;
}

出栈pop操作:

Status Pop(LinkStack *S,SElemType *e){
   LinkStackPtr p;
   if(StackEmpty(*S)) return ERROR;
   *e=S->top->data;
   p=S->top;//将栈顶节点赋值给P
   S->top=S->top->next;//使栈顶指针下移一位,指向后一个结点
   free(p);//释放结点p
   S->count--;
   return OK;
}

顺序栈需要确定一个固定的长度,但是存取定位很方便。链栈长度则无限制。如果栈的使用过程中元素变化不可预料,有时很小,有时很大,或者非常大,最好使用链栈;反之则使用顺序栈。

栈的应用

递归

比如斐波那契数列,例子略。
递归:一个直接调用自己或通过一系列的调用函数间接地调用自己的函数。

四则运算表达式求值

后缀(逆波兰)表示法

一种不需要括号的后缀表达法。比如9+(3-1)*3+10/2表示为 9 3 1 - 3 * 10 2 / +.
计算规则:从左到右遍历表达式的每个数字和符号,遇到数字就进栈,遇到是符号,就将处于栈顶两个数字出栈,进行运算,运算结果进栈,一直到最终获得结果。

中缀表达式转后缀表达式

计算规则:从左到右遍历中缀表达式的每个数字和符号,若是数字就输出,即成为后缀表达式的一部分;若是符号,则判断其与栈顶符号的优先级,是右括号或者优先级不高于栈底符号(乘除优先于加减)则栈顶元素依次出栈输出,并将当前符号进栈,一直到最终输出后缀表达式为止。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值