今天刷题卡看到一个将队列和栈结合的一道题,我感觉这到题能是大家对队列和栈能有进一步的了解,但主要还是对队列有进一步的了解
放上题目
这道题是来自力扣上的一道题,这也是博主这几个月没更新的原因,博主因为个人原因刷题去了
https://leetcode.cn/problems/implement-stack-using-queues/
这是这道题的链接
这道题的要求就是让我们利用队列的方式来实现栈的功能。首先我们来说一说栈的特性,栈最主要最让人深知的一个特性就是先进后出,后进先出的原则。队列的原则是从队尾进入从队头出,这很明显不满足栈的功能。
我们想要利用队列的特性来完成栈的功能,该怎么首先呢?
首先我们得对队列的结构进行选择,我们一般都是选择链表最为队列的结构,这是因为队列的功能链表都能实现。例如对头出数据可以利用链表的头出数据,队尾进数据可以利用链表的尾插来进数据。
我们想要完成这道题的话,肯定不止利用到一个队列,这道题需要两个队列来进行操作处理:
首先一个队列存入数据
另外一个队列空出来
当要出栈顶数据时,将存入数据的队列按头出的方式存入另外一个空的队列中去,直到之前的那个队列剩下一个数据就是栈顶元素
当要进数据时,数据尾插到非空的队列中去才行
typedef int QDataType;
typedef struct QueueNode
{
struct QueueNode* next;
QDataType data;
}QueueNode;
typedef struct Queue
{
QueueNode* head;
QueueNode* tail;
}Queue;
typedef struct {
Queue q1;
Queue q2;
} MyStack;
void QueueInit(Queue* pq);
void QueueDestroy(Queue* pq);
void QueuePush(Queue* pq, QDataType x);
void QueuePop(Queue* pq);
QDataType QueueFront(Queue* pq);
QDataType QueueBack(Queue* pq);
int QueueSize(Queue* pq);
bool QueueEmpty(Queue* pq);
//给队列进行初始化
void QueueInit(Queue* pq)
{
assert(pq);
pq->head = NULL;
pq->tail = NULL;
}
//对队列进行销毁
void QueueDestroy(Queue* pq)
{
assert(pq);
QueueNode* cur = pq->head;
while (cur)
{
QueueNode* next = cur->next;
free(cur);
cur = next;
}
pq->head = pq->tail = NULL;
}
//队列是对头出数据,队尾进数据
//尾插进数据
void QueuePush(Queue* pq, QDataType x)
{
assert(pq);
QueueNode* node = (QueueNode*)malloc(sizeof(QueueNode));
node->next = NULL;
node->data = x;
if (pq->head == NULL)
{
pq->head = pq->tail = node;
}
else
{
pq->tail->next = node;
pq->tail = node;
}
}
//头删出数据
void QueuePop(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
QueueNode* next = pq->head->next;
free(pq->head);
pq->head = next;
if (pq->head == NULL)
{
pq->tail = NULL;
}
}
//返回队头的数据
QDataType QueueFront(Queue* pq)
{
assert(pq);
return pq->head->data;
}
//返回队尾的数据
QDataType QueueBack(Queue* pq)
{
assert(pq);
return pq->tail->data;
}
//返回这个队列的大小
int QueueSize(Queue* pq)
{
assert(pq);
int num = 0;
QueueNode* cur = pq->head;
while (cur)
{
num++;
cur = cur->next;
}
return num;
}
//判断这个队列是否为空
bool QueueEmpty(Queue* pq)
{
assert(pq);
return pq->head == NULL;
}
MyStack* myStackCreate() {
MyStack *st = (MyStack *)malloc(sizeof(MyStack));
QueueInit(&st->q1);
QueueInit(&st->q2);
return st;
}
void myStackPush(MyStack* obj, int x) {
if(!QueueEmpty(&obj->q1))
{
QueuePush(&obj->q1,x);
}
else
{
QueuePush(&obj->q2,x);
}
}
int myStackPop(MyStack* obj) {
//假设q1队列为空,q2队列不为空
Queue * empty = &obj->q1;
Queue * notempty = &obj->q2;
//首先要对两个队列进行判断
//如果队列q1不为空
if(!QueueEmpty(&obj->q1))
{
empty = &obj->q2;
notempty = &obj->q1;
}
/*
将不为空的队列以队头出的方式输入到为空的队列中去,直到不为空的队列中只有一个数据停止
*/
while(QueueSize(notempty) > 1)
{
QueuePush(empty,QueueFront(notempty));
QueuePop(notempty);
}
int top = QueueFront(notempty);
QueuePop(notempty);
return top;
}
int myStackTop(MyStack* obj) {
if(!QueueEmpty(&obj->q1))
{
return QueueBack(&obj->q1);
}
else
{
return QueueBack(&obj->q2);
}
}
bool myStackEmpty(MyStack* obj) {
return QueueEmpty(&obj->q1) && QueueEmpty(&obj->q2);
}
void myStackFree(MyStack* obj) {
/*
为什么不能直接释放掉obj?因为在这个栈中还有两个队列,如果只是释放放掉栈的空间的话,会导致俩个队列的空间还存留在内存当中,这会导致内存泄漏。所以必须先将两个队列的空间给释放掉,最后在把栈的空间释放
*/
QueueDestroy(&obj->q1);
QueueDestroy(&obj->q2);
free(obj);
}