栈的定义和特点
栈是限定仅在表尾进行插入或删除操作的线性表。对栈来说,表尾端称为栈顶(top),表头端称为栈底(bottom)。不含元素的空表空表称为空栈。
栈也被称为先进后出的线性表
栈的抽象数据类型定义
ADT Stack{
数据对象:D={ai | ai∈ElemSet, i=1,2,…,n,n≥0}
数据关系:R={ <a(i-1) , ai> | a(i-1), ai ∈D,i=1,2,…n} 约定a(n)为栈顶,a1为栈底
基本操作:
InitStack(&S) 构造一个空栈SDestoryStack(&S) 销毁栈S
ClearStack(&S) 将S清为空栈
StackEmpty(S) 若栈S为空栈,返回true,否则返回false
StackLength(S) 返回S的元素个数,即栈的长度
GetTop(S) 返回S的栈顶元素,不修改栈顶指针
Push(&S,e) 插入元素e为新的栈顶元素
Pop(&S,&e) 删除S的栈顶元素,并用e返回其值
StackTraverse(S) 从栈底到栈顶依次对S的每个数据元素进行访问
顺序栈的表示和实现
指针top指示栈顶元素在顺序栈中的位置,指针base指示栈底元素在顺序栈中的位置。当top和base值相等时,表明空栈。
顺序栈定义如下:
//顺序栈的存储结构
#define MAXSIZE 100 //顺序栈存储空间的初始分配量
typedef struct
{
SElemType*base; //栈底指针
SElemType*top; //栈顶指针
int stacksize; //栈可用的最大容量
}SqStack;
①初始化
顺序栈的初始化操作就是为顺序栈动态分配一个预定义大小的数组空间
【算法步骤】
- 为顺序栈动态分配一个最大容量为MAXSIZE的数组空间,使base指向这段空间的基地址,即栈底
- 栈顶指针top初始化为base,表示栈为空
Status InitStack(SqStack &S)
{//构造一个空栈s
S.base=new SElemType[MAXSIZE]; //为顺序栈动态分配一个最大容量
if(!S.base) exit(OVERFLOW); //存储分配失败
S.top=S.base; //空栈
S.stacksize=MAXSIZE; //stacksize置为栈的最大容量MAXSIZE
return OK;
}
②入栈
入栈操作就是在栈顶插入一个新的元素
Status Push(SqStack &S,SElemType e)
{//插入元素e为新的栈顶元素
if(S.top-s.base==S.stacksize) return ERROR; //栈满
*S.top++=e; //元素e压入栈顶,栈顶指针加1
return OK;
}
③出栈
出栈操作就是将栈顶元素删除
Status Pop(SqStack &S,SElemType &e)
{//删除栈顶元素,用e返回其值
if(S.top==S.base) return ERROR; //栈空
e=*--S.top; //栈顶指针减一,将栈顶元素赋给e
return OK;
}
④取栈顶元素
当栈非空时,此操作返回当前栈顶元素的值,栈顶指针保持不变
SElemType GetTop(SqStack S)
{//返回S的栈顶元素,不修改栈顶指针
if(S.top!=S.base) //栈非空
return *(S.top-1); //返回栈顶元素的值,栈顶指针不变
}
链栈的表示和实现
链栈定义如下:
//链栈的存储结构
typedef struct StackNode
{
ElemType data;
struct stackNode*next;
}StackNode,*LinkStack;
①初始化
链栈的初始化就是构造一个空栈,直接将栈底指针置空即可
Status InitStack(LinkStack &S)
{//构造一个空栈S,栈顶指针置空
S=NULL;
return OK;
}
②入栈
和顺序栈的入栈操作不同的是,链栈在入栈前不需要判断栈是否满,只需要为入栈元素动态分配一个结点空间。
Status Push(LinkStack &S,SElemType)
{//在栈顶插入元素e
p=new StackNode; //生成新结点
p->data=e; //将新结点数据域置为e
p->next=S; //将新结点插入栈顶
S=p; //修改栈顶指针为p
return OK;
}
③出栈
和顺序栈一样,链栈在出栈前也需要判断栈是否为空,不同的是,链栈在出栈后需要释放出栈元素的栈顶空间。
Status Pop(LinkStack &S,SElemType &e)
{//删除S的栈顶元素,用e返回其值
if(S==NULL) return ERROR; //栈空
e=S->data; //将栈顶元素赋给e
p=S; //用p临时保存栈顶元素空间,以备释放
S=S->next; //修改栈顶指针
delete p; //释放原栈顶元素的空间
return OK;
}
④取栈顶元素
与顺序栈一样,当栈非空时,此操作返回当前栈顶元素的值,栈顶指针S保持不变。
SElemType GetTop(LinkStack S)
{//返回S的栈顶元素,不修改栈顶指针
if(S!=NULL) //栈非空
return S->data; //返回栈顶元素的值,栈顶指针不变
}
借鉴:《数据结构》严蔚敏