队列实现栈
一、题目
二、题目分析
把两个队列拿出来分析
🐚栈进入是1、2、3
,出栈是3、2、1
🐚队列进入是1、2、3
,我们现在要控制出队列是按3、2、1
的顺序
🎁把1、2
放到另一个队列,把 3(栈顶)
拿出去了
🎁同理拿出2
,最后拿出1
1. 准备队列
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;
2. 新建栈
这里需要把所有需要的东西初始化
//初始化队列
void QueueInit(Queue* pq)
{
assert(pq);
pq->head = NULL;
pq->tail = NULL;
}
MyStack* myStackCreate() {
MyStack* st = (MyStack*)malloc(sizeof(MyStack));
QueueInit(&st->q1);//初始化第一个队列
QueueInit(&st->q2);//初始化第二个队列
return st;
}
3. 元素x压入栈顶
🎄q1不为空:
push进去
拿出栈顶,实则此处的4
🎄q1为空:
再push
代码:
//队列进队
void QueuePush(Queue* pq, QDataType x)
{
assert(pq);
QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
assert(newnode);
newnode->data = x;
newnode->next = NULL;
if (pq->head == NULL)
{
pq->head = pq->tail = newnode;
}
else
{
pq->tail->next = newnode;
pq->tail = newnode;
}
}
//判断队列是否为空
bool QueueEmpty(Queue* pq)
{
assert(pq);
return (pq->head == NULL);
}
void myStackPush(MyStack* obj, int x) {
if(!QueueEmpty(&obj->q1))
{
QueuePush(&obj->q1, x);
}
else
{
QueuePush(&obj->q2, x);
}
}
4. 移除并返回栈顶元素
我们发现,每次需要栈顶的时候,需要把栈顶前的数先放到另外一个队列中
移动之后
这样我们就可以拿到栈顶
按照这个思路写下去
//取到队头的数据
QDataType QueueFront(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->head->data;
}
//出队
void QueuePop(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
QueueNode* next = pq->head->next;
if (next == NULL)
{
pq->tail = NULL;
}
free(pq->head);
pq->head = next;
}
//队列中数据个数
int QueueSize(Queue* pq)
{
assert(pq);
int n = 0;
QueueNode* cur = pq->head;
while (cur)
{
n++;
cur = cur->next;
}
return n;
}
int myStackPop(MyStack* obj) {
Queue* emptyQ = &obj->q1;
Queue* nonemptyQ = &obj->q2;
//确认哪个队列是空
if(!QueueEmpty(&obj->q1))
{
emptyQ = &obj->q2;
nonemptyQ = &obj->q1;
}
while(QueueSize(nonemptyQ) > 1)
{
//将队头的数据拿出,放入另一个队列
QueuePush(emptyQ, QueueFront(nonemptyQ));
//取完放入之后删除原来所在地方
QueuePop(nonemptyQ);
}
//还剩最后一个数,就是栈顶,拿出数据之后,pop掉
int top = QueueFront(nonemptyQ);
QueuePop(nonemptyQ);
return top;
}
5. 返回栈顶元素
🔕偷工减料想了一下,难道不可以在myStackPop
的基础上,不移除,直接返回吗
🔔但细节上,myStackPop
将整个思路的套路彻底打乱了,这样操作之后,两个队列当中没有一个为空
,之前的一些操作就实现不了,这里就老老实实用以前找到队列的队尾(即我们需要的栈顶)的接口来实现
//取到队尾的数据
QDataType QueueBack(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->tail->data;
}
int myStackTop(MyStack* obj) {
if(!QueueEmpty(&obj->q1))//如果队列1不为空
{
return QueueBack(&obj->q1);//返回队列1队尾
}
else
{
return QueueBack(&obj->q2);//为空,返回队列2队尾
}
}
6. 判断栈是否为空
两个队列都为空的话说明没有元素了
bool myStackEmpty(MyStack* obj) {
return QueueEmpty(&obj->q1) && QueueEmpty(&obj->q2);//两个队列都不为空
}
7. 销毁栈
销毁这个栈要先销毁两个队列
//销毁队列
void QueueDestroy(Queue* pq)
{
assert(pq);
QueueNode* cur = pq->head;
while(cur != NULL)
{
QueueNode* next = cur->next;
free(cur);
cur = next;
}
pq->tail = NULL;
pq->head = NULL;
}
void myStackFree(MyStack* obj) {
QueueDestroy(&obj->q1);
QueueDestroy(&obj->q2);
free(obj);
}
三、整体代码(c语言版本)
🎊本来就是很纠结写不写这个,因为c写这种栈和队列插口要重新写一遍很麻烦,但是这个思路上很复杂也很好,所以还是写了一下
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)
{
assert(pq);
pq->head = NULL;
pq->tail = NULL;
}
MyStack* myStackCreate() {
MyStack* st = (MyStack*)malloc(sizeof(MyStack));
QueueInit(&st->q1);//初始化第一个队列
QueueInit(&st->q2);//初始化第二个队列
return st;
}
//队列进队
void QueuePush(Queue* pq, QDataType x)
{
assert(pq);
QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
assert(newnode);
newnode->data = x;
newnode->next = NULL;
if (pq->head == NULL)
{
pq->head = pq->tail = newnode;
}
else
{
pq->tail->next = newnode;
pq->tail = newnode;
}
}
//判断队列是否为空
bool QueueEmpty(Queue* pq)
{
assert(pq);
return (pq->head == NULL);
}
void myStackPush(MyStack* obj, int x) {
if(!QueueEmpty(&obj->q1))
{
QueuePush(&obj->q1, x);
}
else
{
QueuePush(&obj->q2, x);
}
}
//取到队头的数据
QDataType QueueFront(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->head->data;
}
//出队
void QueuePop(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
QueueNode* next = pq->head->next;
if (next == NULL)
{
pq->tail = NULL;
}
free(pq->head);
pq->head = next;
}
//队列中数据个数
int QueueSize(Queue* pq)
{
assert(pq);
int n = 0;
QueueNode* cur = pq->head;
while (cur)
{
n++;
cur = cur->next;
}
return n;
}
int myStackPop(MyStack* obj) {
Queue* emptyQ = &obj->q1;
Queue* nonemptyQ = &obj->q2;
//确认哪个队列是空
if(!QueueEmpty(&obj->q1))
{
emptyQ = &obj->q2;
nonemptyQ = &obj->q1;
}
while(QueueSize(nonemptyQ) > 1)
{
//将队头的数据拿出,放入另一个队列
QueuePush(emptyQ, QueueFront(nonemptyQ));
//取完放入之后删除原来所在地方
QueuePop(nonemptyQ);
}
//还剩最后一个数,就是栈顶,拿出数据之后,pop掉
int top = QueueFront(nonemptyQ);
QueuePop(nonemptyQ);
return top;
}
//取到队尾的数据
QDataType QueueBack(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->tail->data;
}
int myStackTop(MyStack* obj) {
if(!QueueEmpty(&obj->q1))//如果队列1不为空
{
return QueueBack(&obj->q1);//返回队列队尾
}
else
{
return QueueBack(&obj->q2);
}
}
bool myStackEmpty(MyStack* obj) {
return QueueEmpty(&obj->q1) && QueueEmpty(&obj->q2);//两个队列都不为空
}
//销毁队列
void QueueDestroy(Queue* pq)
{
assert(pq);
QueueNode* cur = pq->head;
while(cur != NULL)
{
QueueNode* next = cur->next;
free(cur);
cur = next;
}
pq->tail = NULL;
pq->head = NULL;
}
void myStackFree(MyStack* obj) {
QueueDestroy(&obj->q1);
QueueDestroy(&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);
*/