Leetcode刷题之用队列实现栈(C语言版)
- 一、题目描述
- 二、题目要求
- 三、题目示例
- 四、题目解析
- Ⅰ、MyStack* myStackCreate
- Ⅱ、void myStackPush(MyStack* obj, int x)
- Ⅲ、int myStackPop(MyStack* obj)
- Ⅳ、int myStackTop(MyStack* obj)
- Ⅴ、bool myStackEmpty(MyStack* obj)
- Ⅵ、void myStackFree(MyStack* obj)
- 五、完整代码
225、用队列实现栈
一、题目描述
请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop 和 empty)。实现 MyStack 类:①、void push(int x) 将元素 x 压入栈顶。
②、nt pop() 移除并返回栈顶元素。
③、int top() 返回栈顶元素。
④、boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。
二、题目要求
Ⅰ、你只能使用队列的基本操作 —— 也就是 push to back、peek/pop from front、size 和 is empty 这些操作。
Ⅱ、你所使用的语言也许不支持队列。 你可以使用 list (列表)或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。
三、题目示例
四、题目解析
首先我们看到本题是用队列实现栈。那么我们便要对栈和队列的相关特性有一定的了解,例如栈是先进后出的,而队列是先进先出的。如果有伙伴对这两种数据结构有些遗忘的话,建议看一下博主之前的两篇文章,分别是《数据结构——栈的详细介绍》和《数据结构——看完这篇保证你学会队列》。
我们想要解决这道题,首先便要实现一个完整的队列,其中的接口包括初始化队列,销毁队列,入队,出队等,其代码如下:
//定义数据类型
typedef int QueueDataType;
//定义队列结构
typedef struct QueueNode
{struct QueueNode* next;QueueDataType Data;
}Qnode;//定义头、尾指针
typedef struct Queue
{Qnode* phead;Qnode* ptail;int size;
}Queue;//初始化
void InitQueue(Queue* pq);
//销毁
void DestoryQueue(Queue* pq);
//入队
void PushQueue(Queue* pq, QueueDataType x);
//出队
void PopQueue(Queue* pq);
//判空
bool QueueEmpty(Queue* pq);
//获取SIze
int SizeQueue(Queue* pq);
//获取队头元素
QueueDataType QueueFront(Queue* pq);
//获取队尾元素
QueueDataType QueueBack(Queue* pq);void InitQueue(Queue* pq)
{assert(pq);pq->phead = NULL;pq->ptail = NULL;pq->size = 0;
}
//销毁
void DestoryQueue(Queue* pq)
{assert(pq);Qnode* cur = pq->phead;while (cur){Qnode* next = cur->next;free(cur);cur = next;}pq->phead = pq->ptail = NULL;pq->size = 0;
}
//入队
void PushQueue(Queue* pq, QueueDataType x)
{assert(pq);Qnode* newnode = (Qnode*)malloc(sizeof(Qnode));if (newnode == NULL){perror("malloc fail");return;}//赋值newnode->Data = x;newnode->next = NULL;//分情况讨论if (pq->ptail == NULL){assert(pq->phead == NULL);pq->phead = pq->ptail = newnode;}else{pq->ptail->next = newnode;pq->ptail = newnode;}pq->size++;
}
//出队
void PopQueue(Queue* pq)
{assert(pq);assert(!QueueEmpty(pq));//一个节点if (pq->phead->next == NULL){free(pq->phead);pq->phead = pq->ptail = NULL;}//多个节点else{//头删Qnode* next = pq->phead->next;free(pq->phead);pq->phead = next;}pq->size--;}
//判空
bool QueueEmpty(Queue* pq)
{assert(pq);return pq->size == 0;
}
//获取SIze
int SizeQueue(Queue* pq)
{assert(pq);return pq->size;
}
//获取队头元素
QueueDataType QueueFront(Queue* pq)
{assert(pq);assert(!QueueEmpty(pq));return pq->phead->Data;
}
//获取队尾元素
QueueDataType QueueBack(Queue* pq)
{assert(pq);assert(!QueueEmpty(pq));return pq->ptail->Data;
}
构建好队列的各种接口之后,我们需要在Mystack的结构体中创建两个队列变量。代码如下:
typedef struct
{Queue q1;Queue q2;
} MyStack;
Ⅰ、MyStack* myStackCreate
该接口,需要我们在内存中开辟空间,利用malloc函数,并且将q1和q2进行初始化。
MyStack* myStackCreate()
{MyStack*obj=(MyStack*)malloc(sizeof(MyStack));if(obj==NULL){perror("malloc fail");return NULL;}InitQueue(&obj->q1);InitQueue(&obj->q2);return obj;}
Ⅱ、void myStackPush(MyStack* obj, int x)
如果两个队列都为空,那么任选一个进行入队操作即可,后续入队往有数据的队列进行入队操作即可。
void myStackPush(MyStack* obj, int x)
{if(!QueueEmpty(&obj->q1)){PushQueue(&obj->q1,x);}else{PushQueue(&obj->q2,x);}
}
Ⅲ、int myStackPop(MyStack* obj)
最为复杂的便是出栈了,我们的大体思路便是假定q1为空,q2不为空:如果结果相反,则调换一下二者的顺序,我们将不为空的队列进行出队操作,并将其数据压入为空的队列,直到为空的队列中只剩下一个数据,我们将这个数据定义为top,并对其进行出队操作,最后将其进行返回。
Queue*EmptyQ=&obj->q1;Queue*NonEmptyq=&obj->q2;if(!QueueEmpty(&obj->q1)){EmptyQ=&obj->q2;NonEmptyq=&obj->q1;}while(SizeQueue(NonEmptyq)>1){PushQueue(EmptyQ,QueueFront(NonEmptyq));PopQueue(NonEmptyq);}int top=QueueFront(NonEmptyq);PopQueue(NonEmptyq);return top;
Ⅳ、int myStackTop(MyStack* obj)
解决这个接口,我们首先需要找到不为空的那个队列,然后调用其获取队尾数据的函数,最后将这个函数返回的结果返回即可。
int myStackTop(MyStack* obj)
{if(!QueueEmpty(&obj->q1)){return QueueBack(&obj->q1);}else{return QueueBack(&obj->q2);}
}
Ⅴ、bool myStackEmpty(MyStack* obj)
我们需要保证我们的两个队列都为空,这样才能够保证我们创建的队列为空。
bool myStackEmpty(MyStack* obj)
{return QueueEmpty(&obj->q1)&&QueueEmpty(&obj->q2);
}
Ⅵ、void myStackFree(MyStack* obj)
需要先对我们所创建的q1和q2队列进行销毁,然后再对ob进行free操作,以防止内存的泄漏。
void myStackFree(MyStack* obj)
{DestoryQueue(&obj->q1);DestoryQueue(&obj->q2);free(obj);}
五、完整代码
//定义数据类型
typedef int QueueDataType;
//定义队列结构
typedef struct QueueNode
{struct QueueNode* next;QueueDataType Data;
}Qnode;//定义头、尾指针
typedef struct Queue
{Qnode* phead;Qnode* ptail;int size;
}Queue;//初始化
void InitQueue(Queue* pq);
//销毁
void DestoryQueue(Queue* pq);
//入队
void PushQueue(Queue* pq, QueueDataType x);
//出队
void PopQueue(Queue* pq);
//判空
bool QueueEmpty(Queue* pq);
//获取SIze
int SizeQueue(Queue* pq);
//获取队头元素
QueueDataType QueueFront(Queue* pq);
//获取队尾元素
QueueDataType QueueBack(Queue* pq);void InitQueue(Queue* pq)
{assert(pq);pq->phead = NULL;pq->ptail = NULL;pq->size = 0;
}
//销毁
void DestoryQueue(Queue* pq)
{assert(pq);Qnode* cur = pq->phead;while (cur){Qnode* next = cur->next;free(cur);cur = next;}pq->phead = pq->ptail = NULL;pq->size = 0;
}
//入队
void PushQueue(Queue* pq, QueueDataType x)
{assert(pq);Qnode* newnode = (Qnode*)malloc(sizeof(Qnode));if (newnode == NULL){perror("malloc fail");return;}//赋值newnode->Data = x;newnode->next = NULL;//分情况讨论if (pq->ptail == NULL){assert(pq->phead == NULL);pq->phead = pq->ptail = newnode;}else{pq->ptail->next = newnode;pq->ptail = newnode;}pq->size++;
}
//出队
void PopQueue(Queue* pq)
{assert(pq);assert(!QueueEmpty(pq));//一个节点if (pq->phead->next == NULL){free(pq->phead);pq->phead = pq->ptail = NULL;}//多个节点else{//头删Qnode* next = pq->phead->next;free(pq->phead);pq->phead = next;}pq->size--;}
//判空
bool QueueEmpty(Queue* pq)
{assert(pq);return pq->size == 0;
}
//获取SIze
int SizeQueue(Queue* pq)
{assert(pq);return pq->size;
}
//获取队头元素
QueueDataType QueueFront(Queue* pq)
{assert(pq);assert(!QueueEmpty(pq));return pq->phead->Data;
}
//获取队尾元素
QueueDataType QueueBack(Queue* pq)
{assert(pq);assert(!QueueEmpty(pq));return pq->ptail->Data;
}typedef struct
{Queue q1;Queue q2;
} MyStack;MyStack* myStackCreate()
{MyStack*obj=(MyStack*)malloc(sizeof(MyStack));if(obj==NULL){perror("malloc fail");return NULL;}InitQueue(&obj->q1);InitQueue(&obj->q2);return obj;}void myStackPush(MyStack* obj, int x)
{if(!QueueEmpty(&obj->q1)){PushQueue(&obj->q1,x);}else{PushQueue(&obj->q2,x);}
}int myStackPop(MyStack* obj)
{Queue*EmptyQ=&obj->q1;Queue*NonEmptyq=&obj->q2;if(!QueueEmpty(&obj->q1)){EmptyQ=&obj->q2;NonEmptyq=&obj->q1;}while(SizeQueue(NonEmptyq)>1){PushQueue(EmptyQ,QueueFront(NonEmptyq));PopQueue(NonEmptyq);}int top=QueueFront(NonEmptyq);PopQueue(NonEmptyq);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)
{DestoryQueue(&obj->q1);DestoryQueue(&obj->q2);free(obj);}/*** Your MyStack struct will be instantiated and called as such:* MyStack* obj = myStackCreate();* myStackPush(obj, x);* int param_2 = myStackPop(obj);* int param_3 = myStackTop(obj);* bool param_4 = myStackEmpty(obj);* myStackFree(obj);
*/