栈的概念
栈:是一个种特殊的线性表,只允许在固定的一端进行插入与删除元素的操作。在进行数据插入一端称为栈顶,进行删除操作的另一端成称栈底。栈中不含任何数据元素的时候称为空栈。栈中的元素遵守后进先出的原则。也叫先进后出。
举个例子:栈在我们的生活中的应用是经常见到的。我们大家在小时候应该都会玩过玩具枪,玩具枪里面的弹夹大家都不陌生吧,一颗一颗的子弹压入弹夹中,最后压入的子弹是最先被发射出来的。
在软件应用中,也是非常普遍的。比如我们在用浏览器浏览东西时,不管什么浏览器都会有一个“返回键”,点击后会按照你访问的顺序逆序后退。有时候我们在浏览一些东西的时候会弹出一个弹窗,一不小心点了进去,一看“性感女优,在线发牌”,顿时慌了起来千万不能被看到,粉身碎骨浑不怕,要留清白在人间。赶忙狂点返回键,这才留住了“清白”。
栈是一个特殊的线性表,只能在栈顶进行数据插入以及删除,特殊之处在于它限制了这个线性表的插入和删除位置,它始终只能在栈顶进行。
栈的插入操作叫做进栈,也称压栈、入栈。如同子弹一般一颗一颗压入弹夹中。
栈的删除操作叫做出栈,也称弹栈。如同弹出弹夹中的子弹。
进栈出栈变化形式
想一下,最先进栈的元素是不是就只能最后出栈呢?
是不一定的。要看是什么情况。栈对线性表的插入和删除的位置进行了限制,但没有对出栈入栈的时间进行限制。所以说并不是得所有元素都入栈了才可以出栈,可以进一个出一个也可以进多个再依次都出,但切记不能越级出。
这里有道题大家可以拿来练练手。
若进栈序列为 1,2,3,4 ,进栈过程中可以出栈,则下列不可能的一个出栈序列是()
A 1,4,3,2
B 2,3,4,1
C 3,1,4,2
D 3,4,2,1
A选项:1入栈就出栈,接着2、3、4依次入栈,4出,3出,2出,出栈次序是:1,4,3,2。
B选项:1、2入栈,2出栈。3入栈再出栈,4入栈再出栈,最后栈中只剩下1出栈,出栈次序是:2,3,4,1。
D选项:1、2、3入栈,3出栈,4入栈再出栈,最后栈中剩下1、2。2出,1出, 出栈次序是:3,4,2,1。
而C选项:1、2、3入栈,3出了但栈中还有1、2。2是在栈顶,应先出的是2,1是在栈底,如果先出1的话就越级了。
因此这道题应该是选 C。通过这道题我们要知道栈中元素的入栈出栈操作只能在栈顶位置执行。
栈的各个接口实现:
栈的实现一般可以使用数组或者链表来实现的,相对而言使用数组的结构来实现的话会更优一点。因为数组在尾上插入删除数据的代价比较小。如果使用链表的话,首先就得遍历找到尾再进行插入或删除的操作。数组是支持下标随机访问的。
typedef int STDataType; //根据要存入的数据类型而修改
typedef struct Stack
{
STDataType* data;
int top; //栈顶
int capacity; //容量
}Stack;
栈的初始化
//初始化
void StackInit(Stack*ps)
{
assert(ps);
ps->data = (STDataType*)malloc(sizeof(STDataType)* 3);
ps->capacity = 3;
ps->top = 0;
}
入栈
//入栈
void StackPush(Stack*ps,STDataType x)
{
assert(ps);
if (ps->capacity == ps->top) //相等表示容量不足需扩容
{
STDataType* newp = (STDataType*)realloc(ps->data, sizeof(STDataType)*(ps->capacity + 3));
if (newp == NULL)
{
printf("realloc Fail\n");
exit(-1);
}
else
{
ps->data = newp;
ps->capacity += 3; //容量增加
}
}
ps->data[ps->top] = x; //要插入的元素放入栈顶
ps->top++;
}
出栈
//出栈
void StackPop(Stack* ps)
{
assert(ps);
if (ps->top > 0) //栈顶大于0表示栈中还有元素
{
ps->top--;
}
else
{
printf("栈为空\n");
}
}
获取栈顶元素
STDataType StackTop(Stack*ps)
{
assert(ps);
if (ps->top > 0)
{
return ps->data[ps->top - 1];
}
//栈空返回-1
return -1;
}
获取栈中元素个数
//获取栈个数
int StackSize(Stack *ps)
{
assert(ps);
return ps->top;
}
判断栈是否为空
栈如果为空返回true,不为空返回false。
bool StackEmpty(Stack*ps)
{
assert(ps);
//栈顶等于0表示空,相反则不为空
return ps->top == 0;
}
销毁栈
//销毁栈
void StackDestroy(Stack*ps)
{
assert(ps);
free(ps->data);
ps->capacity = 0;
ps->top = 0;
}
附加一个跟栈相关的编程题:有效的括号