栈的基本概念
数据结构三要素——逻辑结构、数据的运算、存储结构(物理结构)
栈的定义
栈(Stack)是只允许在一端进行插入或删除操作的线性表
- 栈顶:允许插入和删除的一端
- 栈底:不允许插入和删除的一端 。固定的
- 空栈:不含任何元素的空表
特点:后进先出
(Last In First Out) 即LIFO
栈的基本操作
InitStack(&S)
初始化栈。构造一个空栈S,分配内存空间。
DestoryStack(&L)
销毁栈。销毁并释放栈S所占用的内存空间。
Push(&S,x)
进栈。若栈S未满,则将X加入是使之成为新栈顶。
Pop(&S,&x)
出栈。若栈S非空,则弹出栈顶元素,并用x返回。
GetTop(S,&x)
读栈顶元素。若栈S非空,则用x返回栈顶元素。
n个不同元素进栈,出栈元素不同排列的个数为1/n+1Cn2n。
上述公式成为卡特兰(Catalan)数,可采用数学归纳法证明。
顺序栈的定义
初始化操作
#define MaxSize 10 //定义栈中元素的最大个数
typedef struct{
ElemType data[MaxSize]; //静态数组存放栈中元素
int top; //栈顶指针
}SqStack;
void testStack(){
SqStack S; //声明一个顺序栈
InitStack(S);
}
//判断栈是否为空 利用top的指向判断
bool StackEmpty(SqStack S){
if(S.top == -1)
return true; //栈空
else
return false; //非空
}
进栈操作(增)
#define MaxSize 10 //定义栈中元素的最大个数
typedef struct{
ElemType data[MaxSize]; //静态数组存放栈中元素
int top; //栈顶指针
}SqStack;
//新元素入栈
bool Push(SqStack &S,ElemType x){
if(S.top == MaxSize -1) //栈满,报错
return false;
S.data[++S.top];
return ture;
}
出栈操作(删)
//出栈操作的删除,数据还残留在内存中,只是逻辑上删除了
#define MaxSize 10
typedef struct{
ElemType data[MaxSize];
int top;
}SqStack;
//出栈操作,将栈顶元素删除,并返回删除的值
bool Pop(SqStack &S,ElemType &x){
if(S.top == -1) //判断栈是否为空
return false;
x=S.data[S.top--];
return ture;
}
读栈顶元素操作
#define MaxSize 10
typedef struct{
ElemType data[MaxSize];
int top;
}SqStack;
//读栈顶元素
bool GetTop(SqStack S,ElemType &x){
if(S.top == -1)
return false;
x=S.data[S.top];
return true;
}
顺序栈的缺点:栈的大小不可变
共享栈
利用栈底位置相对不变的特性,可以让两个顺序栈共享一个一维数组空间,将两个栈的栈底分别设置在共享空间的两端,两个栈顶向共享空间的中间延伸。
#define MaxSize 10
typedef struct{
int data[MaxSize];
int top0;
int top1;
}ShStack;
//初始化栈
void InitStack(ShStack &S){
S.top0 = -1;
S.top1 = MaxSize;
}
//判断栈满的条件,top0 + 1 == top1
两个栈的栈顶指针都指向栈顶元素,top0 = -1 时 0号栈为空,top1 == MaxSize 时 1号栈为空;仅党两个栈顶指针相邻(top1 - top0 == 1)时,判断为栈满。当0号栈进栈时,top0先加再赋值,1号栈进栈时top先减1再赋值;出栈时则刚好相反
共享栈是为了更有效地利用存储空间,两个栈的空间相互调节,只有在整个存储空间被沾满时才发生上溢。其存取数据的时间复杂度均为O(1) ,所以对存取效率没有什么影响。