前言
栈的基本概念
- 定义: 只能在表的一端(栈顶)进行插入和删除运算的线性表
- 逻辑结构: 与线性表相同,仍为一对一关系
- 存储结构: 用顺序栈或链栈存储均可,顺序栈更常见
- 运算规则: 只能在栈顶运算,先进后出(FILO)或后进先出(LIFO)
- 栈操作的运算: n个元素依次进栈,出栈序列会有(2n)!/((n+1)*n!*n!)种
数组形式
(top为栈顶元素的位置,后面会详细提到)
一、抽象数据类型(ADT)
- 数据对象:D={ ai |ai∈ ElemType, i=1,2,…,n, n >=0 }
- 数据关系:R={ < a(i-1), ai> | a(i-1),ai ∈ D , i=1,2,…,n }
- 基本操作
InitStack(StackType &S) // 构造一个空栈S
DestroyStack(StackType &S) //销毁栈S
ClearStack (StackType &S) //清空,S为空栈
Stack Empty (StackType S) //判断栈S是否为空,空为true
StackLength(StackType S) //求栈S的长度,即元素个数
Push(StackType &S, ElemType e) // 元素e进栈
Pop(StackType &S,ElemType &e) //元素出栈,用e返回
ElemTypeGetTop(StackType S) //返回S的栈顶元素,不出栈
StackTraverse(StackType S) //遍历栈,从栈底到栈顶
二、顺序表
1.表示和存储
- 顺序栈的表示:
top指示栈顶元素的下标
(top==-1 时,栈空)
stacksize = 4; - 存储结构:
#define MAXSIZE 100
typedef struct{
SElemType *base; /*栈底,顺序存储的起始地址*/
int top; /*栈顶指针,如top=4,即栈顶元素的下标为4*/
int stacksize;
}
2.基本操作
- 顺序栈初始化:
思路:
(1). 申请栈空间,base指向基地址
(2). 设置为空栈,即top=-1
(3). 设置栈的容量
Status InitStack(SqStack &S){
S.base = new SElemType[MAXSIZE];
if(!S.base) return OVERFLOW;
S.top = -1;
S.stackSize = MAXSIZE;
return OK;
}
- 一些简单操作:
判断顺序栈是否为空
bool StackEmpty(SqStack S){
if(S.top==-1) return true;
else return false;
}
求顺序栈的长度
int StackLength(SqStack S){
return S.top+1;
}
清空顺序栈(置空)
Status ClearStack(SqStack S){
if(S.base) S.top = -1;
return OK;
}
销毁顺序栈
Status DestroyStack(SqStack &S){
if(S.base){
delete []s.base;
S.stacksize = 0;
S.base = NULL;
S.top = -1;
}
return OK;
}
- 顺序栈进栈:
思路:
(1)判断是否栈满,若满则出错
(2)元素e压入栈顶
(3)栈顶指针加1
Status Push(SqStack &S,SElemType e){
if(S.top == S.stacksize-1){
S.base = (SElemType)realloc(S.base,(S.stacksize+STACKINCREMENT)*sizeof(SElemType));
S.stacksize += STACKINCREMENT;
}
S.top++;
S.base[S.top] = e;
return OK;
}
- 顺序表出栈:
思路:
(1) 判断是否栈空
(2) 获取栈顶元素e
(3) 栈顶指针减1
Status Pop(SqStack &S,SElemType &e){
if(S.top == -1) return ERROR;
e = S.base[S.top--];
return OK;
}
- 去顺序栈栈顶元素:
思路:
(1) 判断是否空栈,若空则返回错误
(2)否则通过栈顶指针获取栈顶元素
(不出栈,只返回其值)
Status GetTop(SqStack S,SElemType &e){
if(S.top==-1) return ERROR;
e = S.base[S.top];
return OK;
}
三、链栈
1.基本结构
运算是受限的单链表,链表头部作为栈顶,没有必要附加头结点。栈顶指针就是链表的头指针。
- 存储结构
typedef struct StackNode{
SElemType data;
struct StackNode *next;
}StackNode, *LinkStack;
LinkStack S;
2. 基本操作
- 链栈的初始化:
void InitStack(LinkStack &S){
S=NULL;
}
- 判断链栈是否为空:
bool StackEmpty(LinkStack S){
if(S==NULL) return TRUE;
else return FALSE;
}
- 链栈进栈:
Status Push(LinkStack &S,SElemType e){
p = new StackNode;
if(!p) return OVERFLOW;
p->data = e;
p->next = S;
S = p;
return OK;
}/*其实就是在单链表表头插入一个元素*/
- 链栈出栈:
Status Pop(LinkStack &S,SElemType &e){
if(S==NULL) return ERROR;
e = S->data;
p = S;
S = S->next;
delete p;
return OK;
}
- 取链栈栈顶元素:
SElemType GetTop(LinkStack S){
if(S==NULL) exit(1);
else return S->data;
}