3.1.1 栈的基本概念
线性表:具有相同数据类型的 n 个数据元素的有限序列,其中 n 为表长
栈(Stack):只允许在一端进行插入或者删除操作的线性表
- 逻辑结构:与普通线性表相同
- 数据运算:插入、删除操作有区别
- 栈顶:允许插入、删除的一端
- 栈底:不允许插入、删除的一端
- 空栈:
- 特点:后进先出(LIFO)
回顾之——线性表基本操作
- 初始化:分配内存空间
- 销毁:释放内存空间
- 插入
- 删除
- 按值查找
- 按位查找
- 其他操作:求表长、输出、判空
总览之——栈的基本操作
- 创建:初始化、分配内存空间
- 销毁:释放内存空间
- 进栈(增):若栈 S 未满,则将 x 加入使之成为新栈顶
- 出栈(删):若栈 S 非空,则弹出栈顶元素,并用 x 返回
- 查:获得栈顶元素,但不删除
- 其他操作:判断是否为空
注意:增删只能在栈顶操作
卡特兰数(Catalan)
问:n 个不同元素进栈,出栈元素不同排列的个数为
3.1.2 顺序栈的实现
顺序栈:用顺序存储方式实现的栈
顺序存储:给各个数据元素分配连续的存储空间,大小为:Maxsize*sizeof(ElemType)
缺点:栈的大小不可变
基本操作:
1、顺序栈的定义
#define Maxsize 10
typedef struct{
Elemtype data[Maxsize]; //静态数组存放栈中元素
int top; //栈顶指针,int形式
}SqStack;
2、初始化操作
//初始化栈
void InitStack(SqStack &S){ //注意是传址
S.top=-1; //初始化栈顶指针
}
//判断栈空
bool StakEmpty(SqStack S){
if(S.top==-1) //栈空
return true;
else //不空
return false;
}
3、进栈操作
//新元素进栈
bool Push(SqStack &S,ElemType x){
if(S.top==Maxsize-1) //栈满,报错
return false;
S.top=S.top+1; //指针+1
S.data[S.top]=x; //指针作为数组下标,让新元素进栈
//上述两行等价于 S.data[++S.top]=x;
}
4、出栈操作
对x传址:&x
栈顶元素出栈,利用栈顶指针作为静态数组下标
注意:数据还残留在内存中,只是逻辑上被删除了
//出栈操作
bool Pop(SqStack &S,ElemType &x){
if(S.top==-1) //栈空,报错
return false;
x=S.data[S.top];
S.top=S.top-1;
//上述两行等价于 x=S.data[S.top--]
return true;
}
5、读取栈顶元素
//读取栈顶元素
bool GetTop(SqStack S,ElemType &x){ //注意!不需要对S传址,x要&x
if(S.top==-1) //栈空,报错
return false;
x=S.data[S.top];
return true;
}
另一种方式,栈顶指针初始指向0
top指向下一个可以插入的位置
则进栈时
//上述两行等价于 S.data[S.top++]=x;
出栈时
//上述两行等价于 x=S.data[--S.top]
栈满的条件
top==MaxSize
共享栈:两个栈共享同一片空间
#define MaxSize 10
typedef struct{
ElemType data[MaxSize];
int top0; //0号栈顶指针
int top1; //1号栈顶指针
}
//初始化栈
void InitStack(ShStack &S){
S.top0=-1;
S.top1=MaxSize;
}
共享栈栈满条件:top0+1==top1
小结:创、增、删、查 T(n)=O(1)
3.1.3 链栈的实现
链栈:用链式存储方式实现的栈
基本操作:创(初始化)、增(进栈)、删(出栈)、查(获取栈顶元素)、判空、判满
回忆:
1、头插法建立单链表(对应进栈)
//后插操作:在p节点之后插入元素e
bool InsertNextNode(LNode *p,ElemType e){
if (p==NULL)
return false;
LNode *s=(LNode *)malloc(sizeof(LNode)); //分配内存给新结点s
if (s==NULL)
return false; //内存分配失败
s->data=e; //用结点s保存数据e
s->next=p->next;
p->next=s; //将结点s连到p之后,先连s尾,再连s头
}
2、单链表的删除(对应出栈)
链栈的定义
//链栈的定义
typedef struct Linknode{
ElemType data; //数据域
struct Linenode *next; //指针域
}*LiStack; //栈类型定义
带头结点的初始化
不带头结点的初始化(推荐)
(代码待补)
进出栈只能在栈顶一端进行(链头作为栈顶)