💭前言:
建议本题和LeetCode232对比实现
syseptember的个人博客:LeetCode232.栈模拟队列http://t.csdn.cn/HCEDg
题目
思路
❗注意:本题的逻辑结构是栈,物理结构是队列,我们需要通过2个队列模拟栈的操作。
🔨 元素入栈:如果queue1为空就将元素插入到q1中。
🔨元素出栈:如果queue1不为空,那么将queue1中除队尾数据全部删除并插入到queue2,再删除queue的队尾数据。
🔨继续入栈:因为queue1为空,所以将元素插入到queue2中
🔨继续出栈:和第一次一样,将queue2的数据除队尾全部删除插入到queue1中,最后删除queue的队尾。
❗注意:对比上述2次入栈、出栈我们可以发现---每次出栈都是将非空队列的数据导入到空队列数据,每次进栈都是将元素插入到非空队列中,所以后续在入栈、出栈函数中仅有queue1和queue2是不够的,我们还需要判断它们谁是空队列、谁是非空队列。
🔺总结:
代码
❗注意:
①下面的pop函数复用了top函数,因为它们都需要返回栈顶元素。
②之所以队列实现一个取队尾的函数是为了在栈中取栈顶元素只需取出非空队列的队尾
💬由于作者还没有学习C++的STL库,所以只能手写一个队列:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
typedef int QDataType;
//队列由于具备先进后出的特点,使用链表实现效率更高,因为数组头插和头删的效率比链表低
typedef struct Qnode
{
QDataType val;
struct Qnode* next;
}Qnode;
typedef struct
{
Qnode* head;//指向队列头
Qnode* tail;//指向队列尾
int size;//记录队列有效元素个数
}Queue;
//队列的初始化
extern void QueueInit(Queue* pq);
//队列为空
extern bool QueueEmpty(const Queue* pq);
//入队列
extern void QueuePush(Queue* pq, QDataType x);
//出队列
extern void QueuePop(Queue* pq);
//获取队列头部元素
extern QDataType QueueFront(const Queue* pq);
//获取队列尾部元素
extern QDataType QueueBack(const Queue* pq);
//获取队列元素个数
extern int QueueSize(const Queue* pq);
//销毁队列
extern void QueueDestroy(Queue* pq);
//队列的初始化
void QueueInit(Queue* pq)
{
assert(pq);
pq->head = pq->tail = NULL;
pq->size = 0;
}
//队列是否为空
bool QueueEmpty(const Queue* pq)
{
assert(pq);
//return pq->head == NULL && pq->tail == NULL;
return pq->size == 0;
}
//入队列
void QueuePush(Queue* pq, QDataType x)
{
assert(pq);
Qnode* newnode = (Qnode*)malloc(sizeof(Qnode));
assert(newnode);
newnode->val = x;
newnode->next = NULL;
//链表为空
if (pq->tail == NULL)
{
assert(pq->head == NULL);//链表为空尾指针一定为空
pq->head = pq->tail = newnode;
}
else
{
//直接尾插
pq->tail->next = newnode;
pq->tail = newnode;
}
pq->size++;
}
//出队列
void QueuePop(Queue* pq)
{
assert(pq);
//空队列不能删除
assert(!QueueEmpty(pq));
//只有1个节点
if (pq->size == 1)
{
Qnode* tmp = pq->head;
pq->head = pq->tail = NULL;
free(tmp);
}
//2节点及以上
else
{
//头删
Qnode* tmp = pq->head;
pq->head = pq->head->next;
free(tmp);
}
pq->size--;
}
//获取队列头部元素
QDataType QueueFront(const Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->head->val;
}
//获取队列尾部元素
QDataType QueueBack(const Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->tail->val;
}
//获取队列元素个数
int QueueSize(const Queue* pq)
{
assert(pq);
return pq->size;
}
//销毁队列
void QueueDestroy(Queue* pq)
{
assert(pq);
Qnode* cur = pq->head;
while (cur)
{
Qnode* next = cur->next;
free(cur);
cur = next;
}
pq->head = pq->tail = 0;
pq->size = 0;
}
typedef struct {
Queue q1;
Queue q2;
} MyStack;
MyStack* myStackCreate() {
MyStack* stack = (MyStack*)malloc(sizeof(MyStack));
//初始化2个队列
QueueInit(&stack->q1);
QueueInit(&stack->q2);
return stack;
}
void myStackPush(MyStack* obj, int x) {
//将数据插入到非空队列中
if (!QueueEmpty(&obj->q1))
{
QueuePush(&obj->q1, x);
}
else
{
QueuePush(&obj->q2, x);
}
}
int myStackTop(MyStack* obj) {
//找出非空队列和空队列
Queue* pNonEmptyQ = &obj->q1;
Queue* pEmptyQ = &obj->q2;
if (!QueueEmpty(&obj->q2))
{
pNonEmptyQ = &obj->q2;
pEmptyQ = &obj->q1;
}
//非空队列的队尾就是栈顶元素
return QueueBack(pNonEmptyQ);
}
//pop可以复用top函数
int myStackPop(MyStack* obj) {
//保存栈顶数据
int ret = myStackTop(obj);
//这里一定要定义成指向空队列的指针
Queue* pNonEmptyQ = &obj->q1;
Queue* pEmptyQ = &obj->q2;
if (!QueueEmpty(&obj->q2))
{
pNonEmptyQ = &obj->q2;
pEmptyQ = &obj->q1;
}
//非空队列像空队列导入数据
while (QueueSize(pNonEmptyQ) > 1)
{
QueuePush(pEmptyQ, QueueFront(pNonEmptyQ));
QueuePop(pNonEmptyQ);
}
//删除栈顶元素--也就是删除非空队列队尾
QueuePop(pNonEmptyQ);
return ret;
}
bool myStackEmpty(MyStack* obj) {
//两个队列都为空栈为空
return QueueEmpty(&obj->q1) && QueueEmpty(&obj->q2);
}
void myStackFree(MyStack* obj) {
QueueDestroy(&obj->q1);
QueueDestroy(&obj->q2);
free(obj);
}