题目链接:232.用栈实现队列
题目描述:
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(
push
、pop
、peek
、empty
):
实现
MyQueue
类:
void push(int x)
将元素 x 推到队列的末尾int pop()
从队列的开头移除并返回元素int peek()
返回队列开头的元素boolean empty()
如果队列为空,返回true
;否则,返回false
说明:
- 你 只能 使用标准的栈操作 —— 也就是只有
push to top
,peek/pop from top
,size
, 和is empty
操作是合法的。- 你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。
示例 1:
输入: ["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 <= x <= 9
- 最多调用
100
次push
、pop
、peek
和empty
- 假设所有操作都是有效的 (例如,一个空的队列不会调用
pop
或者peek
操作)
思路:
定义两个栈,一个用来入队列,一个用来出队列
1.队列的结构
typedef struct {Stack pushST;Stack popST;
} MyQueue;
定义pushST来实现入队列,popST来实现出队列。
2.队列的创建
申请我们定义的队列的空间,并将pushST和popST初始化,返回指向队列的指针。
MyQueue* myQueueCreate() {MyQueue* pq = (MyQueue*)malloc(sizeof(MyQueue));StackInit(&pq->pushST);StackInit(&pq->popST);return pq;
}
3.入队列
void myQueuePush(MyQueue* obj, int x)
将数据直接插入pushST即可。
void myQueuePush(MyQueue* obj, int x) {StackPush(&obj->pushST,x);
}
4.出队列
当popST中没有数据时:
如图所示,现在队列中有4个数据,现在要将数据1出队列,对应pushST里的位于栈底的1 ,由于我们需要将1移至栈顶才能使1出栈,所以这里我们将pushST中的所有元素全部循环取栈顶,出栈顶,插入到pushST中。
再将popST出栈即可。
代码实现:
if (StackEmpty(&obj->popST)){while(!StackEmpty(&obj->pushST)){StackPush(&obj->popST,StackTop(&obj->pushST));StackPop(&obj->pushST);}}
当popST中有数据时:
直接保存popST栈顶,出栈。
代码实现:
int top = StackTop(&obj->popST);StackPop(&obj->popST);
完整代码:
int myQueuePop(MyQueue* obj) {if (StackEmpty(&obj->popST)){while(!StackEmpty(&obj->pushST)){StackPush(&obj->popST,StackTop(&obj->pushST));StackPop(&obj->pushST);}}int top = StackTop(&obj->popST);StackPop(&obj->popST);return top;
}
5.返回队列开头元素
int myQueuePeek(MyQueue* obj)
![]()
若popST为空,将pushST中的元素,取栈顶,出栈顶,插入到popST中,再用top记录popST的栈顶并返回。
![]()
若popST不为空,直接返回popST栈顶即可。
代码实现:
int myQueuePeek(MyQueue* obj) {if (StackEmpty(&obj->popST)){while(!StackEmpty(&obj->pushST)){StackPush(&obj->popST,StackTop(&obj->pushST));StackPop(&obj->pushST);}} int top = StackTop(&obj->popST);return top;
}
6.判空
bool myQueueEmpty(MyQueue* obj)
![]()
若popST与pushST中任意一个不为空,则队列不为空,返回false。
若popST与pushST都为空,则队列为空,返回true。
代码实现:
bool myQueueEmpty(MyQueue* obj) {return StackEmpty(&obj->pushST) && StackEmpty(&obj->popST);
}
7.销毁
void myQueueFree(MyQueue* obj)
在将popST和pushST销毁后,由于obj是接收了myQueueCreate()的返回值,函数中申请了MyQueue类型的空间,所以还得将obj所指向的空间释放并置空。
代码实现:
void myQueueFree(MyQueue* obj) {StackDestroy(&obj->pushST);StackDestroy(&obj->popST);free(obj);obj = NULL;
}
代码总览:
typedef int STDataType;
typedef struct Stack
{STDataType* _a;int _top; // 栈顶int _capacity; // 容量
}Stack;// 初始化栈
void StackInit(Stack* ps)
{ps->_a = NULL;ps->_top = ps->_capacity = 0;
}// 入栈
void StackPush(Stack* ps, STDataType data)
{assert(ps);if (ps->_top == ps->_capacity){int newcapacity = ps->_capacity == 0 ? 4 : 2 * ps->_capacity;STDataType* tmp = (STDataType*)realloc(ps->_a, newcapacity * sizeof(STDataType));if (tmp == NULL){perror("realloc");exit(1);}ps->_a = tmp;ps->_capacity = newcapacity;}ps->_a[ps->_top++] = data;
}// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0
int StackEmpty(Stack* ps)
{assert(ps);return ps->_top == 0;
}// 出栈
void StackPop(Stack* ps)
{assert(!StackEmpty(ps));--ps->_top;
}// 获取栈顶元素
STDataType StackTop(Stack* ps)
{assert(!StackEmpty(ps));return ps->_a[ps->_top - 1];
}// 获取栈中有效元素个数
int StackSize(Stack* ps)
{assert(ps);return ps->_top;
}// 销毁栈
void StackDestroy(Stack* ps)
{if (ps->_a)ps->_a = NULL;ps->_top = ps->_capacity = 0;
}typedef struct {Stack pushST;Stack popST;
} MyQueue;MyQueue* myQueueCreate() {MyQueue* pq = (MyQueue*)malloc(sizeof(MyQueue));StackInit(&pq->pushST);StackInit(&pq->popST);return pq;
}void myQueuePush(MyQueue* obj, int x) {StackPush(&obj->pushST,x);
}int myQueuePop(MyQueue* obj) {if (StackEmpty(&obj->popST)){while(!StackEmpty(&obj->pushST)){StackPush(&obj->popST,StackTop(&obj->pushST));StackPop(&obj->pushST);}}int top = StackTop(&obj->popST);StackPop(&obj->popST);return top;
}int myQueuePeek(MyQueue* obj) {if (StackEmpty(&obj->popST)){while(!StackEmpty(&obj->pushST)){StackPush(&obj->popST,StackTop(&obj->pushST));StackPop(&obj->pushST);}} int top = StackTop(&obj->popST);return top;
}bool myQueueEmpty(MyQueue* obj) {return StackEmpty(&obj->pushST) && StackEmpty(&obj->popST);
}void myQueueFree(MyQueue* obj) {StackDestroy(&obj->pushST);StackDestroy(&obj->popST);free(obj);obj = NULL;
}