1.栈的定义
栈是只允许在一端进行插入或删除操作的线性表。
特点:先进后出(LIFO)
2. 栈的基本操作
InitStack(&S):初始化栈。构造一个空栈S,分配内存空间。
DestroyStack(&L):销毁栈。销毁并释放栈S所占内存空间。
Push(&S,x):进栈,若栈S未满,则将x加入使之成为新栈项。
Pop(&S,&x):出栈,若栈S非空,则弹出栈顶元素,并用x返回。
GetTop(S,&x):读取栈顶元素。若栈S非空,则用x返回栈顶元素。
其他常用操作:
StackElemty(S):判断一个栈S是否为空。若S为空,则返回true,否则返回false。
3.顺序栈
缺点:栈的大小不可变
(1)顺序栈的定义
#define MaxSize 10 //定义栈中元素最大个数
typedef struct{
ElemType data[MaxSize]; //静态数组存放栈中元素
int top; //栈顶指针
}SqStack;
void testStack(){
SqStack S; //声明一个顺序栈(分配空间)
//后续操作...
}
(2)初始化操作
#define MaxSize 10
typedef struct{
ElemType data[MaxSize];
int top;
}Sqstack;
//初始化栈
void InitStack(SqStack &S){
S.top = -1; //初始化栈顶指针
}
void testStack(){
SqStack S; //声明一个顺序栈(分配空间)
InitStack(S);
//后续操作...
}
//判断栈空
bool StackEmpty(SqStack S){
if(S.top == -1)
return true;
else
return false;
}
(3)进栈操作
#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.top = S.top+1 //指针先加1
S.data[S.top] = x; //新元素入栈
return true;
}
(4)出栈操作
#define MaxSize 10
typedef struct {
ElemType data[MaxSize];
}
//出栈操作
bool Pop(SqStack &S,ElemType &x){
if(S.top == -1) //栈空,报错
return false;
x = S.data[S.top]; //栈顶元素先出栈
S.top = S.top-1; //指针再减1
return true;
}
(5)读取栈顶元素操作
#define MaxSize 10
typrdef struct {
ElemType data[MaxSize];
int top;
}SqStack;
//出栈操作
bool Pop(SqStack S,ElemType &x){
if(S.top == -1)
return false;
x = S.data[S.top]; //x记录栈顶元素
return true;
}
(6)另一种方式
将栈初始化为-1的后续操作和初始化为0的后续操作不同。
初始化为0的后续操作:
//先进栈再移指针
S.data[S.top] = x;
S.top = S.top+1;
//先移指针再出栈
S.top = S.top-1;
x = S.data[S.top];
(7)共享栈(两个栈共享同一片空间)
两个栈元素分别从两个方向进栈。
#define MaxSize 10
typedef struct{
ElemType data[MaxSize];
int top0; //0号栈栈顶指针
int top1; //1号栈栈顶指针
}ShStack;
//初始化栈
void InitStack(ShStack &S){
S.top0 = -1; //初始化栈顶指针
S.top1 = MaxSize;
}
栈满的条件:top0+1==top1
销栈之后系统内存会自动回收。
4.链栈
(1)链栈的定义
typedef struct Linknode{
ElemType data; //数据域
struct Linknode *next; //指针域
} *LinkStack; //栈类型定义
(2)重要的基本操作(推荐不带头结点)
和单链表的操作相同,但栈只能在链表的一端进行操作。
创(初始化),增(进栈),删(出栈),查(获取栈顶元素)