题目中给出,让我们应用两个队列实现栈,首先我们先来想一下,栈是先进后出,队列是先进先出。所以我们就需要应用两个队列来回导才能实现栈的特点。因为这道题是基于队列来实现的,所以在下方若有看不懂的函数名称可以去栈和队列(二)中找到。
1.MyStrack
首先我们需要在结构体中存储我们的两个队列,后续方便通过结构体来调用两个队列。
typedef struct
{
Queue q1;
Queue q2;
} MyStack;
2.myStackCreate()
对其进行初始化,首先我们需要先开辟一块空间用来存储两个队列。然后我们调用QueueInit()函数来对两个队列进行初始化。
MyStack* myStackCreate()
{
MyStack*obj=(MyStack*)malloc(sizeof(MyStack));
QueueInit(&(obj->q1));
QueueInit(&(obj->q2));
return obj;
}
3.myStackPush()
对栈进行插入,首先我们需要调用QueueEmpty()函数判断两个队列哪个不为空,再调用QueuePush()函数将数据直接插入到不为空的那个队列里就可以了。
void myStackPush(MyStack* obj, int x)
{
if(!QueueEmpty(&(obj->q1)))
{
QueuePush(&(obj->q1),x);
}
else
{
QueuePush(&(obj->q2),x);
}
}
4.myStackPop()
因为我们已经知道栈的删除是删除后进的数据,队列的删除是删除先进的数据。其删除的位置不同,所以不能混为一谈。所以我们需要把非空的队列中的前size-1个数据都挪到空的队列中。首先我们就需要先判断那个队列是空的。所以,依据我们之前做过的题,我们可以使用假设法,先假设q1为空,若q1不为空,再将空的改为q2。现在我们就用empty和nonempty来代表空队列和非空队列了。然后我们应用QueuePush()函数和QueueFront()函数来将非空队列中的头数据插入到空队列中,直到非空链表中的数据个数为1时停止,取出非空队列中的数据,就是我们需要的数据。
int myStackPop(MyStack* obj)
{
Queue*empty=&(obj->q1);
Queue*nonempty=&(obj->q2);
if(!QueueEmpty(&(obj->q1)))
{
empty=&(obj->q2);
nonempty=&(obj->q1);
}
while(QueueSize(nonempty)>1)
{
QueuePush(empty,QueueFront(nonempty));
QueuePop(nonempty);
}
int top=QueueFront(nonempty);
QueuePop(nonempty);
return top;
}
5.myStackTop()
由于栈是先进后出,队列是先进先出,所以栈的Top就是队列中后进的那个数据。所以我们首先需要判断哪个队列为非空队列,再调用QueueBack()函数返回非空队列中的尾数据就可以了。
int myStackTop(MyStack* obj)
{
if(!QueueEmpty(&(obj->q1)))
{
return QueueBack(&(obj->q1));
}
else
{
return QueueBack(&(obj->q2));
}
}
6.myStackEmpty()
判断队列是否为空,需要两个队列同时为空,所以只需要调用QueueEmpty()函数,并返回两个队列进行与运算的值就可以了。
bool myStackEmpty(MyStack* obj)
{
return QueueEmpty(&(obj->q1))&&QueueEmpty(&(obj->q2));
}
7.myStackFree()
由于我们刚刚将两个队列存储在了一个结构体中,所以在销毁时不能直接将结构体销毁,而是应该先销毁两个队列,再销毁结构体。
void myStackFree(MyStack* obj)
{
QueueDestory(&(obj->q1));
QueueDestory(&(obj->q2));
free(obj);
}
总结
整道题的基本思路与代码就讲解完毕了,下面附上本题的完整代码,如果大家感兴趣的话可以自行尝试哦~
typedef int QDataType;
typedef struct QueueNode
{
QDataType val;
struct QueueNode* next;
}QNode;
typedef struct Queue
{
QNode* phead;
QNode* ptail;
int size;
}Queue;
//队列的初始化
void QueueInit(Queue* pq);
//队列的插入
void QueuePush(Queue* pq, QDataType x);
//队列的删除
void QueuePop(Queue* pq);
//统计队列内的数据个数
int QueueSize(Queue* pq);
//获取队列的头数据
QDataType QueueFront(Queue* pq);
//获取队列的尾数据
QDataType QueueBack(Queue* pq);
//队列的判空
bool QueueEmpty(Queue* pq);
//队列的销毁
void QueueDestory(Queue* pq);
//队列的初始化
void QueueInit(Queue* pq)
{
assert(pq);
pq->phead = NULL;
pq->ptail = NULL;
pq->size = 0;
}
//队列的插入
void QueuePush(Queue* pq, QDataType x)
{
assert(pq);
QNode* newnode = (QNode*)malloc(sizeof(QNode));
if (newnode == NULL)
{
perror("malloc fail");
exit(1);
}
newnode->next = NULL;
newnode->val = x;
if (pq->ptail == NULL)
{
pq->phead = pq->ptail = newnode;
}
else
{
pq->ptail->next = newnode;
pq->ptail = newnode;
}
pq->size++;
}
//队列的删除
void QueuePop(Queue* pq)
{
assert(pq);
assert(pq->size != 0);
//方法一:后判是否为只剩一个节点
//QNode* next = pq->phead->next;
//free(pq->phead);
//pq->phead = next;
//if (pq->phead == NULL)
//{
// pq->ptail = NULL;
//}
//pq->size--;
//方法二:先判是否为只剩一个节点
if (pq->phead->next == NULL)
{
pq->phead = pq->ptail = NULL;
pq->size = 0;
}
else
{
QNode* next = pq->phead->next;
free(pq->phead);
pq->phead = next;
pq->size--;
}
}
//统计队列内的数据个数
int QueueSize(Queue* pq)
{
assert(pq);
return pq->size;
}
//获取队列的头数据
QDataType QueueFront(Queue* pq)
{
assert(pq);
assert(pq->phead);
return pq->phead->val;
}
//获取队列的尾数据
QDataType QueueBack(Queue* pq)
{
assert(pq);
assert(pq->ptail);
return pq->ptail->val;
}
//队列的判空
bool QueueEmpty(Queue* pq)
{
assert(pq);
return pq->size == 0;
}
//队列的销毁
void QueueDestory(Queue* pq)
{
assert(pq);
QNode* pcur = pq->phead;
while (pcur)
{
QNode* next = pcur->next;
free(pcur);
pcur = next;
}
pq->phead = pq->ptail = NULL;
pq->size = 0;
}
typedef struct
{
Queue q1;
Queue q2;
} MyStack;
MyStack* myStackCreate()
{
MyStack*obj=(MyStack*)malloc(sizeof(MyStack));
QueueInit(&(obj->q1));
QueueInit(&(obj->q2));
return obj;
}
void myStackPush(MyStack* obj, int x)
{
if(!QueueEmpty(&(obj->q1)))
{
QueuePush(&(obj->q1),x);
}
else
{
QueuePush(&(obj->q2),x);
}
}
int myStackPop(MyStack* obj)
{
Queue*empty=&(obj->q1);
Queue*nonempty=&(obj->q2);
if(!QueueEmpty(&(obj->q1)))
{
empty=&(obj->q2);
nonempty=&(obj->q1);
}
while(QueueSize(nonempty)>1)
{
QueuePush(empty,QueueFront(nonempty));
QueuePop(nonempty);
}
int top=QueueFront(nonempty);
QueuePop(nonempty);
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)
{
QueueDestory(&(obj->q1));
QueueDestory(&(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);
*/