栈是限定仅在表尾进行插入和删除操作的线性表。栈又可以称为后进先出(Last In First Out)的线性表,简称LIFO结构。我们把允许插入和删除的一端称为栈顶,另一端称为栈底。
由栈的定义可知,首先,它是一个线性表,也就是说,栈的元素具有线性关系,即前驱后继的关系。只不过它是一种特殊的线性表而已。定义中所谓的在线性表的表尾进行插入和删除操作,此表尾指的是栈顶,而不是栈底。说栈是一种特殊的线性表,其特殊之处就在于限制了线性表的插入和删除位置,始终只能在栈顶进行操作。于是便能理解后进先出的意思了。
栈的顺序存储——顺序栈,即线性表顺序存储的简化。定义一个top变量来指示栈顶元素在数组中的位置,top的变化就代表着顺序栈中数据的变化。规定:栈顶位置的top值必须小于MAXSIZE(栈容量),当栈中只存在一个元素时,top=0,因此通常把栈空的判定条件定为top==-1。栈满的判定条件则为top==MAXSIZE-1。
常见的顺序栈的几种操作:插入、删除、计算长度、判空等
1.插入操作,即入栈操作,又称压栈。
//压栈操作,即插入数据
bool Push(SqStack* s, ElemType e)
{
//栈满
if (s->top == MAXSIZE - 1)
{
return false;
}
//如果栈未满,先让s->top++,之后再将元素e赋值给s->data[]
s->data[++s->top] = e;
return true;
}
2.删除操作,即弹栈。
//弹栈操作,即删除元素
bool Pop(SqStack* s, ElemType* e)
{
//若栈为空,则s->top==-1
if (s->top == -1)
{
return false;
}
//将要删除的元素赋值给e,之后再将栈顶元素减1
*e = s->data[s->top--];
return true;
}
3.计算长度。
//求栈中元素个数
int StackLength(SqStack* s)
{
return s->top+1;
}
4.判空。
//判空操作
void StackEmpty(SqStack* s)
{
if (s->top == -1)
{
printf("栈为空!\n");
}
else
{
if (s->top == MAXSIZE - 1)
{
printf("栈满!\n");
}
else
{
printf("栈不为空!\n");
}
}
}
5.打印。
//打印
void ShowStack(SqStack* s)
{
for (int i = 0; i <= s->top; i++)
{
printf("%d ", s->data[i]);
}
printf("\n");
}
测试函数和声明部分:
#include<stdio.h>
#define MAXSIZE 10 //设置栈容量为10
typedef int ElemType;
typedef struct
{
ElemType data[MAXSIZE]; //数组存储数据元素,最大容量为MAXSIZE
int top; //栈顶
}SqStack;
int main()
{
//初始化top=-1
SqStack s = { { 0 }, -1 };
StackEmpty(&s);
Push(&s, 0);
Push(&s, 1);
Push(&s, 2);
Push(&s, 3);
Push(&s, 4);
Push(&s, 5);
Push(&s, 6);
ShowStack(&s);
StackEmpty(&s);
int len = StackLength(&s);
printf("%d\n", len);
return 0;
}
除了顺序栈之外,还有一种特殊的栈,即两个栈共享一段空间。具体可理解为:两个栈有两个栈底,让一个栈的栈底作为栈的始端,即下标为0处,另一个栈底为栈的末端,即下标为n-1处。如此一来,两个栈如果增加元素,就是两个端点向中间延伸。如此可得栈1为空时,top1=-1,当top2等于n时,即是栈2为空。栈满的判定条件就变成了top1+1==top2了。
共享空间的两个栈的常见操作和顺序栈相同,只是在定义时需要两个栈顶指针,以及压栈的时候需要多传一个参数来标记栈1和栈2.
1.插入,即压栈。
//压栈操作
bool Push(SqStack* s, ElemType e, int StackNum)
{
//栈满
if (s->top2 - s->top1 == 1)
{
return false;
}
//1号栈,top1加1
if (1 == StackNum)
{
s->data[++s->top1] = e;
}
else
{
s->data[--s->top2] = e;
}
return true;
}
2.删除,即弹栈。
//弹栈操作
bool Pop(SqStack* s, ElemType* e, int StackNum)
{
if (1 == StackNum)
{
//1号栈空栈
if (s->top1 == -1)
{
return false;
}
*e = s->data[s->top1--];
}
else
{
//2号栈空栈
if (s->top2 == MAXSIZE)
{
return false;
}
*e = s->data[s->top2++];
}
return true;
}
3.计算长度。
//求栈中元素长度
int StackLength(SqStack* s)
{
int len = s->top1 + 1 + MAXSIZE - s->top2;
return len;
}
4.判空。
//判空
void StackEmpty(SqStack* s)
{
if (s->top1 == -1 && s->top2 == MAXSIZE)
{
printf("栈为空!\n");
}
else
{
if (s->top2 - s->top1 == 1)
{
printf("栈满!\n");
}
else
{
printf("栈不为空!\n");
}
}
}
5.打印。
//打印
void ShowStack(SqStack* s)
{
for (int i = 0; i <= s->top1; i++)
{
printf("%d ", s->data[i]);
}
for (int j = s->top2; j < MAXSIZE; j++)
{
printf("%d ", s->data[j]);
}
printf("\n");
}
测试函数和声明部分:
int main()
{
//数据域为0,1号栈栈顶为-1,2号栈栈顶为MAXSIZE
SqStack s = { { 0 }, -1, MAXSIZE };
Push(&s, 0, 1);
Push(&s, 1, 1);
Push(&s, 2, 1);
Push(&s, 3, 1);
Push(&s, 4, 1);
Push(&s, 5, 2);
Push(&s, 6, 2);
Push(&s, 7, 2);
Push(&s, 8, 2);
Push(&s, 9, 2);
ShowStack(&s);
int len = StackLength(&s);
printf("%d\n", len);
StackEmpty(&s);
return 0;
}
//声明
typedef int ElemType;
typedef struct
{
ElemType data[MAXSIZE]; //数组存储数据元素最大容量为MAXSIZE
int top1; //1号栈栈顶
int top2; //2号栈栈顶
}SqStack;
以上即是栈的顺序存储的相关内容~~