用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 )
https://leetcode-cn.com/problems/yong-liang-ge-zhan-shi-xian-dui-lie-lcof/
由于C语言的栈要自己实现。前面写好栈的一些接口,代码在最后。
思路:双栈。
先说两个栈的作用:一个栈用于插入,一个栈用于删除。
1.创建队列,两个栈即可。假定s1用于插入,s2用于删除
将两个栈初始化好。
2.尾插,直接在s1里面插入就可以。
3.尾删。由于队列的先进先出的,因此要借助s2来删除。
基本逻辑是:当要删除时,把s1里的元素pop出来,然后push到s2里面。直到s1为空,此时s2的top就是队列的头部,也就是要删除的元素。
在移动数据时,这里有四种情况,每一种都考虑好就行了。
- s1和s2都是空
- s1为空,s2不为空
- s1不为空,s2为空
- s1和s2都不为空
s1和s2都是空
直接返回-1即可,因为整个队列都是空了。
s1为空,s2不为空
这种情况就是没有把原先的元素全部pop完的情况,直接pop s2的top就可以了。
s1不为空,s2为空
这就是还没开始删的时候,直接把s1的元素全部倒到s2,然后pop s2的top就可以了。
两个都不是空
这种形况发生在:刚把s1里面的元素push到s2进行删除后,立刻push了元素。
初始状态:
push元素到s1后:
这是以队列的视角来看就是
6 5 4 3 2 1--------->5 4 3 2 1-------->5 4 3 2 1 1
因此直接pop s2的top就可以了。
可以总结一下:
四种情况中 s1为空,s2不为空和两个都不是空的代码是一样的,其他两种情况单独写就好了。
代码(大部分都是实现栈的接口):
#include <stdio.h>
#include <stdbool.h>
#include <malloc.h>
#include <assert.h>
typedef int StackDataType;
typedef struct stack
{
StackDataType* a;//dynamic
int top;
int capacity;
}stack;
void StackInit(stack* p);
void stackDestroy(stack* p);
void stackPush(stack* p, StackDataType x);
void stackPop(stack* p);
StackDataType stackTop(stack* p);
int stackSize(stack* p);
bool stackEmpty(stack* p);
void StackInit(stack* p)
{
p->a = (StackDataType*)malloc(sizeof(StackDataType) * 4);
p->top = 0;
p->capacity = 4;
}
void stackDestroy(stack* p)
{
free(p->a);
p->capacity = p->top = 0;
p->a = NULL;
p = NULL;
}
void stackPush(stack* p, StackDataType x)
{
assert(p);
if (p->capacity == p->top)
{
p->capacity *= 2;
p->a = (StackDataType*)realloc(p->a, sizeof(StackDataType) * p->capacity);
if (p == NULL)
{
printf("realloc fail");
exit(-1);
}
}
p->a[p->top++] = x;
}
void stackPop(stack* p)
{
assert(p);
p->top--;
}
StackDataType stackTop(stack* p)
{
assert(p);
return p->a[p->top - 1];
}
int stackSize(stack* p)
{
return p->top;
}
bool stackEmpty(stack* p)
{
return p->top == 0;
}
typedef struct {
stack s1;
stack s2;
} CQueue;
CQueue* cQueueCreate() {
CQueue* obj = (CQueue*)malloc(sizeof(stack)*2);
StackInit(&(obj->s1));
StackInit(&(obj->s2));
return obj;
}
void cQueueAppendTail(CQueue* obj, int value) {
stackPush(&obj->s1,value);
}
int cQueueDeleteHead(CQueue* obj) {
//把四种情况都罗列出来就可以了。
if(stackEmpty(&obj->s1)&&stackEmpty(&obj->s2))//两个都是空
return -1;
if(stackEmpty(&obj->s2))//如果s2是空
{
while(!stackEmpty(&obj->s1))
{
stackPush(&obj->s2,stackTop(&obj->s1));
stackPop(&obj->s1);
}
printf("1\n");
int top = stackTop(&obj->s2);
stackPop(&obj->s2);
return top;
}
if(!stackEmpty(&obj->s2) && stackEmpty(&obj->s1))//如果s2不是空且s1是空
{
printf("2\n");
int top = stackTop(&obj->s2);
stackPop(&obj->s2);
return top;
}
if(!stackEmpty(&obj->s1)&&!stackEmpty(&obj->s2))//两个都不是空
{
int top = stackTop(&obj->s2);
stackPop(&obj->s2);
return top;
}
return -1;
}
void cQueueFree(CQueue* obj) {
stackDestroy(&obj->s1);
stackDestroy(&obj->s2);
free(obj);
obj = NULL;
}