栈的抽象数据类型定义
ADT Stack{
数据对象:D={ai|ai∈ElemSet,i=1,2,…,n,n≥0}
数据关系:R1={<ai-1,ai>|ai-1,ai∈D,i=2,…,n}
约定an端为栈顶,a1端为栈底
基本操作:初始化、进栈、出栈、取栈顶元素等
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,并用e返回其值。
}ADT Stack
栈的表示和实现
实现方式:由于栈本身就是线性表,于是栈也有顺序存储和链式存储两种实现方式。
栈的顺序存储——顺序栈
钱的链式存储——链栈
顺序栈
栈的顺序存储——顺序栈
顺序栈的表示
存储方式:同一般线性表的顺序存储结构完全相同,利用一组地址连续的存储单元依次存放自栈底到栈顶的数据元素。栈底一般在低地址端。
① 附设top指针,指示栈顶元素在顺序栈中的位置。
② 另设base指针, 指示栈底元素在顺序栈中的位置。
③ 另外,用stacksize表示栈可使用的最大容量
为了方便操作,通常top指示真正的栈顶元素之上的下标地址,不是最大下标(stacksize-1)
使用数组作为顺序栈存储方式的特点:
简单方便、但易产生溢出(数组大小固定)
上溢(overflow):栈已经满,又要压入元素
下溢(underflow):栈已经空,还要弹出元素
注:上溢是一种错误,使问题的处理无法进行;而下溢十般认为是一种结束条件,即问题处理结束。
顺序栈的实现
顺序栈的数据类型定义:
#define maxsize 100
typedef struct{
SElemType *base;//栈底指针
SElemType *top;//栈顶指针
int stacksize;//栈可用最大容量
}SqStack;
顺序栈的图示:
顺序栈基本操作的实现
1、顺序栈的初始化
Status InitStack(SqStack &S){
S.base=new SElemType[maxsize];//或s.base=(SElemType*)malloc(maxsize*sizeof(SElemType));
if(!S.base)
exit(overflow);//存储分配失败
S.top=S.base;//栈顶指针等于栈底指针
S.stacksize=maxsize;
return ok;
}
2、属性栈判断是否为空
status StackEmpty(SqStack S){//若栈为空,返回true,否则返回false
if(S.top==S.base)
return ture;
else
return false;
}
2、求顺序表的长度
int StackLength(SqStack S){
return S.top-S.base;
}
3、清除顺序表
Status ClearStack(SqStack S){
if(S.base)
S.top=S.base;
return ok;
}
4、销毁顺序表
Status DestroyStack(SqStack &S){
if(S.base)
delete S.base;
S.stacksize=0;
S.base=S.top=null;
return ok;
}
5、顺序表的入栈
【算法思路】
① 判断是否栈满,若满则出错(上溢)
② 元素e压入栈顶
③ 栈顶指针加1
Status Push(SqStack &S,SElemType e){
if(S.top-S.base==S.stacksize)//栈满
return error;
S.top++=e;//同 *S.top=e; S.top++;
return ok;
}
6、顺序栈的出栈
① 判断是否栈空,若空则出错(下溢)
② 栈顶指针减1
③ 获取栈顶元素e
Status Pop(SqStack &S,SElemType &e){//若栈不空,则删除S的栈顶元素,用e返回其值,并返回ok
if(S.top==S.base)//等价于if(StackEmpty(S))
return error;
e=*--S.top;//同 --S.top; e=*S.top;
return ok;
}
链栈
钱的链式存储——链栈
链栈的表示
存储方式:链栈是运算受限的单链表,只能在链表头部进行操作。
① 链表的头指针就是栈顶;
② 不需要头结点;
③ 基本不存在栈满的情况;
④ 空栈相当于头指针指向空;
⑤ 插入和删除仅在栈顶处执行。
typedef struct StackNode{
SELemType data;
struct StackNode *next;
}StackNode,*LinkStack;//定义的这个结构是StackNode类型,再用这个类型定义一个指向*LinkStack结点的指针类型
LinkStack S;//用S来表示stack栈,这个栈是指向这个结点的指针型
链栈的实现
1、链栈的初始化
void InitStack(LinkStack &S){//构造一个空栈,栈顶指针置为空
S=NULL;
return ok;
}
2、判断链栈是否为空
Status StackEmpty(LinkStack S){//头指针S为空链栈就为空
if(S==NULL)
return true;
else
return false
}
3、链栈的入栈
Status Push(LinkStack &S,SElemType e){
p=new StackNode;//生成新结点p
p->data=e;//将新结点数据域置为e
p->next=S;//将新结点插入栈顶
S=p;//修改栈顶指针
return ok;
}
4、链栈的出栈
Status Pop(LinkStack &S,SElemType &e){//删除的值用e返回
if(S==NULL)
return error;
e=S->data;
p=S;
S=S->next;
delete p;
return ok;
}
5、取栈顶元素
SElemType GetTop(LinkStack S){
if(S!=NULL)
return S->data;
}