原题链接:用栈实现队列
思路
栈的特性是先进后出,而队列的特性是先进先出,也就是说,如果把一串数据放进栈里面,它会倒着拿出来,但是队列是会正着拿出来。这里题目给了两个栈,如果我们将数据放到一个栈里面,再从这个栈里面拿出来放到另一个栈里面,那取出来不就是成正的了吗?
为了便于区分,我们将第一个栈命名为pushs,因为入队的数据都必须先放在这个栈里面,第二个栈命名为pops,因为如果要出队或者取最先入队的数据,必须先将第一个栈的数据全部转移到这个栈里面,如果没能全部转移,那么数据就会造成混乱,无法做到先进先出。
代码实现
- 既然要用到两个栈,那需要之前写的栈函数:
typedef int STDataType;
typedef struct Stack
{
STDataType* a;
int top;
int capacity;
}ST;
//初始化
void StackInit(ST* ps)
{
assert(ps);
ps->a = (STDataType*)malloc(sizeof(STDataType) * 4);
if (ps->a == NULL)
{
exit(-1);
}
ps->capacity = 4;
//top初始为0,top指向栈顶元素的下一个元素,top初识为-1,top指向栈顶的元素
ps->top = 0;
}
//销毁
void StackDestory(ST* ps)
{
assert(ps);
free(ps->a);
ps->a = NULL;
ps->top = ps->capacity = 0;
}
//入栈
void StackPush(ST* ps, STDataType x)
{
assert(ps);
if (ps->top == ps->capacity)
{
STDataType* tmp = realloc(ps->a, ps->capacity * 2 * sizeof(STDataType));
if (tmp == NULL)
{
exit(-1);
}
else
{
ps->a = tmp;
ps->capacity *= 2;
}
}
ps->a[ps->top] = x;
ps->top++;
}
//出栈
void StackPop(ST* ps)
{
assert(ps);
ps->top--;
}
//取栈顶的数据
STDataType StackTop(ST* ps)
{
assert(ps);
assert(ps->top>0);
return ps->a[ps->top - 1];
}
//求数据的个数
int StackSize(ST* ps)
{
assert(ps);
return ps->top;
}
//判断是否为空
bool StackEmpty(ST* ps)
{
assert(ps);
return ps->top == 0;
}
- 队列用两个栈表示
typedef struct {
ST pushs;
ST pops;
} MyQueue;
- 创建一个队列
MyQueue* myQueueCreate() {
MyQueue* q = (MyQueue*)malloc(sizeof(MyQueue));
if(q==NULL)
{
exit(-1);
}
StackInit(&q->pushs);//初始化两个栈
StackInit(&q->pops);
return q;
}
- 入队
void myQueuePush(MyQueue* obj, int x) {
StackPush(&obj->pushs, x);//这里只需要往pushs栈里面插入即可,需要出队时再插入到pops
}
- 出队
int myQueuePop(MyQueue* obj) {
//pops为空说明数据全在pushs中,如果不为空说明pops还有数据,此时栈顶的数据就是先入队的数据
if(StackEmpty(&obj->pops))
{
while(!StackEmpty(&obj->pushs))//pushs队列不为空时执行循环
{
StackPush(&obj->pops,StackTop(&obj->pushs));//将pushs队列里的数据放到pops中
StackPop(&obj->pushs);//销毁pushs队列中栈顶的数据
}
}
int ret=StackTop(&obj->pops);//取出pops栈顶的数据
StackPop(&obj->pops);//销毁pops栈顶数据
return ret;
}
- 取出前面入队的数据
int myQueuePeek(MyQueue* obj) {
if(StackEmpty(&obj->pops))
{
while(!StackEmpty(&obj->pushs))
{
StackPush(&obj->pops,StackTop(&obj->pushs));
StackPop(&obj->pushs);
}
}
int top=StackTop(&obj->pops);
return top;
}
这里的实现方式和上一个出队一样,唯一的不同是没有销毁pops栈顶的数据
- 检查是否为空
bool myQueueEmpty(MyQueue* obj) {
return StackEmpty(&obj->pops)&&StackEmpty(&obj->pushs);
}
只有当pops和pushs都为空时,队列才为空
- 销毁队列
void myQueueFree(MyQueue* obj) {
StackDestory(&obj->pops);//销毁pops
StackDestory(&obj->pushs);//销毁pushs
free(obj);//释放指针obj
}