题目一:实现一个栈,要求实现Push(出栈)、Pop(入栈)、Min(返回最小值)的时间复杂度为O(1)
本题目的GitHub地址
-
本题目的实现思路比较简单,使用两个栈,一个栈是用来存储数字,就是普通的数据,在代码中这个栈为
Stack
-
结构体的设计:数字+出现次数,另一个栈便用来存储结构体,在代码中这个栈为
NumStack
,这个栈的栈顶永远存的是Stack
栈中的最小值和最小值个数构成的结构体 -
所以我们将要设计的这个栈命名为
DoubleStack
,提供入栈,出栈,返回最小值得接口和其它基本接口 -
入栈:首先我们先考虑入栈,入栈的时候呢,对于Stack肯定是必须要入栈的,对于NumStack的话就需要考虑了,如果NumStack是空栈,那么肯定是第一次进入元素,所以两个栈都要存东西,而且对于第一次存入的应该将最小值对应的结构体设置为1
-
如果
NumStack
栈不为空的话,那么在压栈之前就需要比较大小,如果比NumStack
栈栈顶元素还小的话就需要将这个较小值压栈,如果相等的话就对栈顶元素的结构体的num+1即可! -
出栈:首先还是先要获取栈顶元素,因为不是每一次入
Stack
栈的元素都能存入到NumStack
中,所以要出栈的元素和NumStack
的栈顶相等的话就将对应的结构体的count属性-1,要是count原本就是1,那么直接将此元素在NumSatck
中出栈即可! -
上一步只是判断
NumStack
中的元素是否需要出栈,但是将Stack
中的元素出栈是必要的,所以最后将Stack
中的元素弹栈!
GIF演示过程——入栈
GIF演示过程——出栈
void DoubleStackPush(DoubleStack* ds, IDataType x)
{
SDataType s;
SDataType ret;
assert(ds);
//如果结构体栈为空
if(NStackEmpty(&ds->nst) == 0)
{
s.count = 1;
s.num = x;
StackPush(&ds->st,x);
NStackPush(&ds->nst, s);
}
else
{
StackPush(&ds->st, x);
//如果入栈的元素小于最小值记录栈的栈顶
if(x < NStackTop(&ds->nst).num)
{
s.num = x;
s.count = 1;
//将此元素的对应结构体入栈
NStackPush(&ds->nst, s);
}
else if (x == NStackTop(&ds->nst).num)
{
//相等的情况
ret = NStackTop(&ds->nst);
NStackPop(&ds->nst);
ret.count += 1;
NStackPush(&ds->nst, ret);
}
}
}
void DoubleStackPop(DoubleStack* ds)
{
SDataType ret;
assert(ds);
//先获取结构体栈的栈顶元素
ret = NStackTop(&ds->nst);
//如果像个相等就做结构体计数-1或者出栈操作
if(ret.num == StackTop(&ds->st))
{
if(ret.count == 1)
{
NStackPop(&ds->nst);
}
else
{
ret.count--;
NStackPop(&ds->nst);
NStackPush(&ds->nst, ret);
}
}
//将原本存数字出栈
StackPop(&ds->st);
}
题目二:一个数组实现两个栈(共享栈)
本题需要使用一个数组来完成两个栈,于是最容易实现这两个栈的方法就是奇偶栈!
数组中的奇数位用来存储一个栈的数据,偶数位用来存储另一个栈的数据!
#include "ShareStack.h"
void ShareStackInit(ShareStack* pss)
{
assert(pss);
pss->_top1 = 0;
pss->_top2 = 1;
}
//which 1/2
void ShareStackPush(ShareStack* pss, SSDataType x, int which)
{
assert(pss && (which == 1 || which == 2));
if (pss->_top1 < N && pss->_top2 < N)
{
if (which == 1)
{
pss->_a[pss->_top1] = x;
pss