栈
限定仅在表尾进行插入和删除操作的线性表,允许插入和删除的一端称为栈顶,另一端称为栈底,不含元素的称为空栈,栈又称后进先出的线性表,简称LIFO(last in first out)结构
栈的抽象数据类型
ADT 栈(stack)
Data
同线性表,元素具有相同类型,相邻元素具有前驱和后继的关系。
Operation
InitStack(*s); //初始化操作,建立一个空栈s
DestroyStack(*s); //若栈存在,删除栈
ClearStack(*s); //清空栈
StackEmpty(s); //若栈为空,则返回true,若不为空则返回false
GetTop(s,*e); //若栈存在,且非空,则用e返回s栈顶的元素
扫描二维码关注公众号,回复: 5828286 查看本文章Push(*s,e); //若栈s存在,压入新的元素e使之成为栈顶元素
Pop(*s,*e); //删除栈s中的栈顶元素,并用e返回其值
StackLength(s); //返回栈s的元素个数
栈的顺序存储结构
结构定义
typedef int SElemType;
typedef struct
{
SElemType data[MAXSIZE]; //定义数组用于存放栈元素,0为栈底
int top; //该变量用于指向栈顶所在,为-1代表空栈
}SqStack;
进栈操作(push)
Status Push(SqStack *s,SELemType e)
{
if(s->top == MAXSIZE-1) //栈满
return error;
s->top++;
s-data[s->top] = e;
return ok;
}
出栈操作(pop)
Status Pop(SqStack *s,SElemType *e)
{
if(s->top == -1) //空栈
return error;
*e = s->data[s->top];
s->top --;
return ok;
}
两栈共享空间
对于元素类型相同的栈,可以共用一个数组,栈1的栈底为0,而栈2的栈底为n-1。
栈满的条件top1 + 1 = top2
需要定义参数stackNumber来判断是哪个栈进行操作
结构定义
typedef struct
{
SElemType data[MAXSIZE];
int top1; //栈1栈顶指针
int top2; //栈2栈顶指针
}SqDoubleStack;
压入(push)
Status Push(SqDoubleStack *s,SElemType e,int stackNumber)
{
if(s->top+1 == s->top2)
return error; //栈满
if(stackNumber == 1)
s->data[++s->top1] = e;
if(stackNumber == 2)
s->data[--s->top2] = e;
return ok;
}
弹出(pop)
Status Pop(SqDouble *s,SElemType *e,int stackNumber)
{
if(stackNumber == 1)
{
if(s->top1 == -1)
return error;
*e = s->data[s->top1--];
}
else if(stackNumber == 2)
{
if(s->top2 == MAXSIZE)
return error;
*e = s->data[s->top2++];
}
return ok;
}
栈的链式存储结构
对于链栈,栈顶多放于头部,使栈顶指针与头指针合二为一,同时头节点也不需要
头指针指向空则代表空栈,基本不存在满栈的情况
结构定义
typedef struct StackNode //节点结构体
{
SElemType data;
struct StackNode *next;
}StackNode ,*LinkStackPtr;
typedef struct LinkStack //记录头指针和计数
{
LinkStackPtr top;
int count;
}LinkStack;
压入
Status Push(LinkStack *s, SElemType e)
{
LinkStackPtr s = (LINkStackPtr)malloc(sizeof(StackNode)); //新建节点s
s->data = e; //给新节点数据赋值
s->next = s->top; //s的下一个节点为原第一个节点
s->top = s; //更新头指针指向s
s->count++; //计数++
return ok;
}
弹出
Status Pop(LinkStack *s,SElemType *e)
{
LinkStackPtr p; //新建结构体指针
if(StackEmpty(*s)) //栈s为空
return error;
*e = s->top->data; //栈顶的数据给e
p = s->top; //指针指向原栈顶
s->top = s->top->next; //头指针指向新的栈顶
free(p); //释放p
s->count--; //计数--
return ok;
}
当使用过程中元素的长度变化过大不可预测时最好使用链栈,而当期变化在可控范围内时,使用顺序栈更好
栈的应用(计算机使用栈来进行以下的操作,集成在系统内部不需要我们自己调用)
一、递归(把一个直接调用自己或者通过一系列的调用语句间接地调用自己的函数,称为递归函数)
二、四则运算表达式
步骤:
1.使用中缀表达式转换为后缀表达式
规则:从左到右遍历符号和数字,若是数字就输出,若是符号则与栈顶的符号比较优先级,是右括号或者优先级高于栈顶的符号则栈顶的符号依次出栈输出,并将当前符号进栈,直到最终输出后缀表达式为止。
2.将后缀表达式进行运算并得出结果
从左到右遍历表达式的每个数字和符号,遇到是数字就进栈,遇到是符号,就将处于栈顶的两个数字出栈,进行运算,运算结果进栈,一直到获得最终的结果。