栈
定义:栈(Stack)是只允许在一端进行插入或删除操作的线性表
栈顶:表尾端
栈底:表头端
空栈:不含元素的空表
特点:后进先出(Last In First Out)LIFO
栈的抽象数据类型定义
ADT Stack{
数据对象:D={
a
1
∣
a
1
∈
E
l
e
m
S
e
t
,
i
=
1
,
2
,
3
⋯
n
,
n
≥
0
a_1|a_1\in ElemSet,i = 1,2,3\cdots n,n\ge0
a1∣a1∈ElemSet,i=1,2,3⋯n,n≥0
数据关系:R1={< a i − 1 , a i a_{i-1},a_i ai−1,ai> | $a_{i-1},a\in D,i=2,\cdots ,n $}
a n a_n an为 栈顶, a 1 a_1 a1为栈底
基本操作:
InitStack(&S) 初始化栈,创造一个空栈
DestoryStack(&S) 销毁栈,销毁并释放栈S所占用的内存空间
Push(&S,x) 进栈,插入元素x为新的栈顶元素
Pop(&S,&x) 出栈,删除S的栈顶元素,并用x返回
GetTop(S,&x) 用x返回S的栈顶元素
StackEmpty(S) 判断一个栈是否为空,为空返回true,否则返回false
StackLength(S) 返回S的元素个数,即长度
}ADT Stack
- n个不同元素进栈,出栈元素不同排列的个数为
1
n
+
1
C
2
n
n
\frac{1}{n+1}C_{2n}^{n}
n+11C2nn
- 例:n = 5时 共有 1 5 + 1 C 10 5 = 1 6 ∗ 10 ∗ 9 ∗ 8 ∗ 7 ∗ 6 5 ∗ 4 ∗ 3 ∗ 2 ∗ 1 = 42 \frac{1}{5+1}C_{10}^{5} = \frac{1}{6}*\frac{10*9*8*7*6}{5*4*3*2*1} = 42 5+11C105=61∗5∗4∗3∗2∗110∗9∗8∗7∗6=42种合法的出栈顺序
栈的表示和实现
顺序栈(静态数组+栈顶指针(整形变量))
顺序栈,即栈的顺序存储结构是利用一组地址连续的存储单元依次存放自栈底到栈顶的数据元素,同时设置指针 top 指示栈顶元素在顺序栈中的位置。
#define MaxSize 10 //定义栈中元素的最大个数
typedef struct {
ElemType data[MaxSize]; //静态数组存放栈中元素
int top; //栈顶指针
}SqStack;
顺序栈的基本操作
初始化栈
void InitStack(SqStack &S){
S.top = -1; //初始化栈顶指针
}
由于C语言中数组的下标约定从0开始,因此初始化栈时将栈顶指针置为-1
栈判空
bool StackEmpty(SqStack S){
if(S.top == -1) //栈空
return true;
else
return false; //非空
}
进栈
bool Push(SqStack &S,ElemType x){
if(S.top == MaxSize-1) //栈满,报错
return false;
S.data[++S.top] = x; //指针先+1,再入栈
return true;
}
出栈
bool Pop(SqStack &S,ElemType &x){
if(S.top == -1) //栈空,报错
return false;
x = S.data[S.top--] ; //先出栈,x带回值,再指针-1
return true;
}
读栈顶元素
bool GetTop(SqStack S,ElemType &x){
if(S.top == -1) //栈空,报错
return false;
x = S.data[S.top] ; //x记录栈顶元素
return true;
}
共享栈
利用栈底位置相对不变的特性,可以让两个顺序栈共享一个一维数组空间,将两个栈的栈底分别置于共享空间的两端,两个栈顶向共享空间的中间延申
top0 = -1 时 0 号栈空
top1 = MaxSize 时 1 号栈空
仅当两个栈顶指针相邻时 top1 - top0 = 1 时,判断为栈满
链栈
采用链式存储的栈称为链栈
链栈的优点是便于多个栈共享存储空间和提高其效率,且不存在栈满上溢的情况
链栈通常采用单链表表示,并规定所有操作都是在单链表的表头进行
typedf struct Linknode{
ElemType data; //数据域
struct Linknode *next; //指针域
}LiStack