来自力扣的一道OJ题:232. 用栈实现队列 - 力扣(LeetCode)
问题描述:
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、
peek、empty):
实现 MyQueue 类:
void push(int x) 将元素 x 推到队列的末尾
int pop() 从队列的开头移除并返回元素
int peek() 返回队列开头的元素
boolean empty() 如果队列为空,返回 true ;否则,返回 false
对应函数的代码:
typedef struct {
} MyQueue;
MyQueue* myQueueCreate() {
}
void myQueuePush(MyQueue* obj, int x) {
}
int myQueuePop(MyQueue* obj) {
}
int myQueuePeek(MyQueue* obj) {
}
bool myQueueEmpty(MyQueue* obj) {
}
void myQueueFree(MyQueue* obj) {
}
示例一:
输入:
["MyQueue", "push", "push", "peek", "pop", "empty"]
[[], [1], [2], [], [], []]
输出:
[null, null, null, 1, 1, false]
解释:
MyQueue myQueue = new MyQueue();
myQueue.push(1); // queue is: [1]
myQueue.push(2); // queue is: [1, 2] (leftmost is front of the queue)
myQueue.peek(); // return 1
myQueue.pop(); // return 1, queue is [2]
myQueue.empty(); // return false
问题分析:
根据问题描述,需要用两个栈来实现队列,我们知道队列是先进先出,而栈是后进先出,所以我
们需要一个入元素的栈和一个出元素的栈,其中入元素的栈作用是用来存储元素的,而出元素的栈
需要将入元素的栈压入出元素的栈中,从而起到了颠倒顺序的作用,即出栈的就是存入的第一个元
素,实现了先进先出的功能。
入队时:将入队元素,压入入元素栈中
出队时:将入栈元素都压入出栈元素中,并取出栈顶元素,删除栈顶元素。
问题实现:
1.void push(int x) 将元素 x 推到队列的末尾
首先应该在结构体内初始化两个栈,名字为push,pop,其次,将入队元素压入push栈中,首先要
写出栈的相关实现:
typedef int STDataType;
typedef struct Stack
{
STDataType* a;
int top;
int capacity;
}ST;
//初始化
void STInit(ST* ps);
//销毁
void STDestory(ST* ps);
//入栈
void STPush(ST* ps, STDataType x);
//出栈
void STPop(ST* ps);
//个数
int STSize(ST* ps);
//判空
bool STEmpty(ST* ps);
//栈顶元素
STDataType STTop(ST* ps);
void STInit(ST* ps)
{
assert(ps);
ps->a = (STDataType*)malloc(sizeof(STDataType) * 4);
if (ps->a == NULL)
{
perror("malloc fail");
return;
}
ps->capacity = 4;
ps->top = -1;
}
void STDestory(ST* ps)
{
assert(ps);
free(ps->a);
ps->capacity = 0;
ps->top = 0;
}
void STPush(ST* ps, STDataType x)
{
assert(ps);
if ((ps->top + 1) == ps->capacity)
{
STDataType* tmp = (STDataType*)realloc(ps->a,
sizeof(STDataType) * ps->capacity * 2);
if (tmp == NULL)
{
perror("realloc fail");
return;
}
ps->a = tmp;
ps->capacity *= 2;
}
ps->a[ps->top + 1] = x;
ps->top++;
}
bool STEmpty(ST* ps)
{
assert(ps);
return ps->top == -1;
}
void STPop(ST* ps)
{
assert(ps);
assert(!STEmpty(ps));
ps->top--;
}
int STSize(ST* ps)
{
assert(ps);
return ps->top + 1;
}
STDataType STTop(ST* ps)
{
assert(ps);
assert(!STEmpty(ps));
return ps->a[ps->top];
}
其次初始化结构体,初始化对应的栈:
typedef struct {
ST pushst;
ST popst;
} MyQueue;
MyQueue* myQueueCreate() {
MyQueue* obj = (MyQueue*)malloc(sizeof(MyQueue));
if (obj == NULL)
{
perror("malloc fault");
return NULL;
}
STInit(&obj->pushst);
STInit(&obj->popst);
return obj;
}
将入队元素压入栈中:
void myQueuePush(MyQueue* obj, int x) {
STPush(&obj->pushst, x);
}
2.对于删除和求开头元素,我们应该先求开头元素比较好,这样在删除时也可以用到开头元素这个
函数。所以先求int peek() 返回队列开头的元素。
这个函数中我们就需要把push栈中的元素压入pop栈中,并取pop栈的栈顶元素,返回。
int myQueuePeek(MyQueue* obj) {
if (STEmpty(&obj->popst))
{
//倒数据
while (!STEmpty(&obj->pushst))
{
STPush(&obj->popst, STTop(&obj->pushst));
STPop(&obj->pushst);
}
}
//取出首元素
return STTop(&obj->popst);
}
3. int pop() 从队列的开头移除并返回元素
int myQueuePop(MyQueue* obj) {
//取出首元素
int front = myQueuePeek(obj);
//删除首元素
STPop(&obj->popst);
//返回
return front;
}
4. boolean empty() 如果队列为空,返回 true ;否则,返回 false
只要push栈和pop栈都为空的话,那么队列一定为空:
bool myQueueEmpty(MyQueue* obj)
{
return STEmpty(&obj->pushst) && STEmpty(&obj->popst);
}
5.销毁结构体,销毁栈
void myQueueFree(MyQueue* obj)
{
STDestory(&obj->pushst);
STDestory(&obj->popst);
free(obj);
}
想必大家现在一定有一个问题,为什么使用栈的操作函数是还要&obj ,首先大家来看看两个结构
体:
typedef struct Stack
{
STDataType* a;
int top;
int capacity;
}ST;
typedef struct {
ST pushst;
ST popst;
} MyQueue;
要想改变pushst里面的数组a,就必须传pushst的地址进去,所以我们应该用(&obj->pushst)来调用
pushst的地址 。
整体代码:
typedef int STDataType;
typedef struct Stack
{
STDataType* a;
int top;
int capacity;
}ST;
//初始化
void STInit(ST* ps);
//销毁
void STDestory(ST* ps);
//入栈
void STPush(ST* ps, STDataType x);
//出栈
void STPop(ST* ps);
//个数
int STSize(ST* ps);
//判空
bool STEmpty(ST* ps);
//栈顶元素
STDataType STTop(ST* ps);
void STInit(ST* ps)
{
assert(ps);
ps->a = (STDataType*)malloc(sizeof(STDataType) * 4);
if (ps->a == NULL)
{
perror("malloc fail");
return;
}
ps->capacity = 4;
ps->top = -1;
}
void STDestory(ST* ps)
{
assert(ps);
free(ps->a);
ps->capacity = 0;
ps->top = 0;
}
void STPush(ST* ps, STDataType x)
{
assert(ps);
if ((ps->top + 1) == ps->capacity)
{
STDataType* tmp = (STDataType*)realloc(ps->a,
sizeof(STDataType) * ps->capacity * 2);
if (tmp == NULL)
{
perror("realloc fail");
return;
}
ps->a = tmp;
ps->capacity *= 2;
}
ps->a[ps->top + 1] = x;
ps->top++;
}
bool STEmpty(ST* ps)
{
assert(ps);
return ps->top == -1;
}
void STPop(ST* ps)
{
assert(ps);
assert(!STEmpty(ps));
ps->top--;
}
int STSize(ST* ps)
{
assert(ps);
return ps->top + 1;
}
STDataType STTop(ST* ps)
{
assert(ps);
assert(!STEmpty(ps));
return ps->a[ps->top];
}
typedef struct {
ST pushst;
ST popst;
} MyQueue;
MyQueue* myQueueCreate() {
MyQueue* obj = (MyQueue*)malloc(sizeof(MyQueue));
if (obj == NULL)
{
perror("malloc fault");
return NULL;
}
STInit(&obj->pushst);
STInit(&obj->popst);
return obj;
}
void myQueuePush(MyQueue* obj, int x) {
STPush(&obj->pushst, x);
}
int myQueuePeek(MyQueue* obj) {
if (STEmpty(&obj->popst))
{
//倒数据
while (!STEmpty(&obj->pushst))
{
STPush(&obj->popst, STTop(&obj->pushst));
STPop(&obj->pushst);
}
}
//取出首元素
return STTop(&obj->popst);
}
int myQueuePop(MyQueue* obj) {
int front = myQueuePeek(obj);
STPop(&obj->popst);
return front;
}
bool myQueueEmpty(MyQueue* obj) {
return STEmpty(&obj->pushst) && STEmpty(&obj->popst);
}
void myQueueFree(MyQueue* obj) {
STDestory(&obj->pushst);
STDestory(&obj->popst);
free(obj);
}
其实把握好思想,这道题很容易写出来。