目录
一、栈的定义
1.1相关概念
·栈是限定仅在表尾进行插入或删除操作的线性表。
Insert(s,n+1,x)
Delete(S,n)
·表头端称桟底(bottom),表尾端称栈顶(top),插入元素到桟顶的操作称为
入栈,从栈顶删除最后一个元素的操作称为出栈
·不含元素的空表称为空栈
特点:后进先出
1.2栈的应用
数值转换、括号匹配的检验、表达式求值、八皇后问题
行编辑程序、函数调用、迷宫求解、递归调用的实现
1.3栈的示意图
思考:假设有3各元素a,b,c,入栈顺序是a,b,c,则它们的出栈顺序有几种可能
一共有5种可能,不会出现cab的情况
二、案例引入
2.1进制转换
十进制整数N向其它进制数d(二、八、十六)的转换
转换法则:除以d倒取余
2.2括号匹配的检验
先入栈的括号后匹配,后入栈的括号先匹配
第3个进来的右括号和第2个左括号进行匹配,所以将左右括号匹配出栈,然后接下来右方括号和第1个左括号匹配不了,所以就验证匹配不成功。
注:在检验过程中,若遇到以下几种情况之一,就可以得出括号不匹配的结论
①当遇到某一个右括号时,栈已空,说明到目前为止,右括号多于左括号
②从栈中弹出的左括号与当前检验的右括号类型不同,说明出现了括号交叉的情况
③算术表达式输入完毕,但栈中还有没匹配的左括号,说明左括号多于右括号
2.3表达式求值
·表达式的组成
操作数:常数、变量
运算符:算术运算符(+-*/)、关系运算符、逻辑运算符
界限符:左右括弧和表达结束符(#)
如:# 3*(7-2)#
三、栈的类型定义
ADT Stack{
数据对象:
D={ai | ai∈ElemSet,i=1,2,3....,n,n>=0}
数据关系:
R1={<a(i-1),ai> | a(i-1),ai∈D,i=2,,,,,n}
基本操作:初始化、进栈、出栈、取栈顶元素等
}ADT Stack
①InitStack(&S) 初始化操作
操作结果:构造一个空栈S
②DestroyStack(&S) 销毁栈操作
初始条件:栈S已存在;操作结果:栈S被销毁
③StackEmpty(S) 判定S是否为空栈
初始条件:栈S已存在;操作结果:若栈S为空栈,则返回TRUE,否则返回FALSE
④StackLength(S) 求栈的长度
初始条件:栈S已存在;操作结果:返回S的元素个数,即栈的长度
⑤GetTop(S,&e) 取栈顶元素
初始条件:栈S已存在;操作结果:用e返回S的栈顶元素
⑥ClearStack(&S) 栈置空操作
初始条件:栈S已存在;操作结果:将S清为空栈
⑦Push(&S,e)入栈操作
初始条件:栈S已存在;操作结果:插入元素e为新的栈顶元素
⑧Pop(&S,&e) 出栈操作
初始条件:栈S已存在且非空;操作结果:删除S的栈顶元素an,并yonge返回其值
四、顺序栈的表示和实现
4.1顺序栈的定义
#define MAXSIZE 100
typedef struct{
SElemType *base; //桟底指针
SElemType *top; //栈顶指针
int stacksize; //栈可用最大容量
}SqStack;
①空栈:base==top 是栈空标志
②栈满:top-base==stacksize(栈的容量)
③栈满的处理方法:
a.报错,返回操作系统
b.分配更大的空间,作为栈的存储空间,将原栈的内容移入新栈
④上溢:栈已经满,又要压入元素;下溢:栈已经空,还要弹出元素
(上溢是一种错误,使问题的处理无法进行;下溢一般认为是一种结束条件,即问题处理结束)
4.2顺序栈的初始化
Status InitStack(SqStack &S){ //构造一个空栈S
S.base=new SElemType[MAXSIZE];
if(!S.base)exit (OVERFLOW); //存储分配失败
S.top=S.base; //栈顶指针等于桟底指针
S.stacksize=MAXSIZE;
return OK;
}
栈中元素个数:top-base
4.3判断顺序栈是否为空
Status StackEmpty(SqStack S){
//若栈为空,返回TRUE;否则返回FALSE
if(S.top==S.base)
return TRUE;
else
return FALSE;
}
4.4求顺序栈长度
int StackLength(SqStack S){
return S.top-S.base;
}
4.5清空顺序栈
Status ClearStack(SqStack S){
if(S.base) S.top=S.base;
return OK;
}
4.6销毁顺序栈
Status DestroyStack(SqStack &S){
if(S.base){
delete S.base;
S.stacksize=0;
S.base=S.top=NULL;
}
return OK;
}
4.7顺序栈的入栈
Status Push(SqStack &S,SElemType e){
if(S.top-S.base==S.stacksize) //栈满
return ERROR;
*S.top++=e;(*S.top=e; S.top++;) //将e赋值给top指针所指向的空间,然后top再指向下一空间
(*S.top的运算优先,所以先将e赋值给S.top,栈顶指针再+1)
return OK;
}
4.8顺序栈的出栈
Status Pop(SqStack &S,SElemType &e){
if(S.top==S.base) //等价于if(StackEmpty(S)) //若栈不为空,则删除S的栈顶元素,用e返回其值(即将删除的元素赋值为e)并返回OK;否则返回ERROR
return ERROR;
e=*--S.top; //先将删除的栈顶元素赋值为e,栈顶指针再-1
return OK;
}
4.9取栈顶元素
SElemType GetTop(SqStack S){ //返回S的栈顶元素,不修改栈顶指针
if(S.top!=S.base) //栈非空
return *(S.top-1); //返回栈顶元素的值,栈顶指针不变
五、链栈的表示和实现
5.1链栈的定义
typedef struct StackNode{
SElemType data;
struct StackNode *next;
}StackNode,*LinkStack;
①链表的头指针就是栈顶
②不需要头结点
③基本不存在栈满的情况
④空栈相当于头指针指向空
⑤插入和删除仅在栈顶处执行
5.3链栈的初始化
void InitStack(LinkStack &s){ //构造一个空栈,栈顶指针置为空
S=NULL;
return OK;
}
5.4判断链栈是否为空
Status StackEmpty(LinkStack S)
if(S==NULL) return TRUE;
else return FALSE;
}
5.5链栈的入栈
Status Push(LinkStack &S,SElemType e){
p=new StackNode; //生成新结点
p->data=e; //将新结点数据域置为e
p->next=s; //将新结点插入栈顶
S=p; //修改栈顶指针
return OK;
}
5.6链栈的出栈
Status Pop(LinkStack &S,SElemType &e){
if(S==NULL)return ERROR;
e=S->data;
p=S;
S=S->next;
delete p;
return OK;
}
5.7取栈顶元素
SElemType GetTop(LinkStack S){ //返回S的栈顶元素,不修改栈顶指针
if(S!=NULL) //栈非空
return S->data; //返回栈顶元素的值,栈顶指针不变
}