目录
一.题目描述
二.解题思路
三.代码实现
💓 博客主页:C-SDN花园GGbond
⏩ 文章专栏:数据结构经典题目刨析(c语言)
一.题目描述
二.解题思路
首先这道题需要我们使用两个队列来完成栈的实现, 这里我们的思路是, 栈的要求是后进先出, 而队列是先进先出, 让两个队列来回导数据, 插入数据时, 插入到不为空的队列中, 如果需要出数据, 先让不为空的队列的前n-1个数据导入到为空的队列中, 然后在出数据, 此时正好就是最后一个数据, 也就是后入先出,
以下是使用两个队列实现栈的基本步骤和原理:
栈的结构定义:包含两个队列的结构
1.初始化:初始化两个空队列,在任意时刻,我们只会使用其中一个队列来进行入栈和出栈操作, 而另一个队列则保持为空。
2.入栈(Push):将元素添加到非空队列的末尾。
如果两个队列都为空,则选择任意一个队列添加元素。
3.出栈(Pop):
如果两个队列都为空,说明栈也为空,此时不能进行出栈操作。将非空队列中的元素(除了最后 一个)逐个出队并入队到另一个队列中,直到只剩下最后一个元 素。此时,该元素就是栈顶元 素,我们将其出队并返回。
4.查看栈顶元素(Peek):
如果两个队列都为空,说明栈也为空,此时不能查看栈顶元素。
如果队列的实现允许查看队尾数据,会比较简单,直接返回非空队列的队尾数据即可
如果队列实现只允许查看队首数据,那么也需要移动元素
我们将非空队列的元素(除了最后一个)逐个出队并入队到另一个队列中,直到只剩下最后一个 元素。此时,该元素就是栈顶元素,将其保存下来,入队到另一个队列中,并在本队列出队(这 样做是为了保持只有一个非空队列)然后返回该元素。
这里画图解释队列元素的移动过程(注意:为方便理解对队列的结构进行了简化)
三.代码实现
步骤如下
1.因为C语言没有自带的队列, 所以我们需要把我们实现的队列写进去, C++会自带的队列.这里我们直接导入
2.创建MyStack,里面需要两个队列, myStackCreate其实也就是我们的初始化, 这里不可以直接 MyStack s, 因为函数里面的创建的变量出了函数就被释放了 ,所以我们需要动态开辟空间. 分别进行初始化
typedef struct {Queue q1;Queue q2;
} MyStack;MyStack* myStackCreate() {MyStack* s = (MyStack*)malloc(sizeof(MyStack));QueueInit(&s->q1);QueueInit(&s->q2);return s;
}
3.入栈, 哪个不为空, 我们就把元素插入到哪个队列, 这里我使用了假设法, 来找出不为空的队列.
void myStackPush(MyStack* obj, int x) {assert(obj);//假设法Queue* Empty = &obj->q1;Queue* nonEmpty = &obj->q2;if(QueueEmpty(&obj->q2)){Empty = &obj->q2;nonEmpty = &obj->q1;}//把数据插入到不为空的队列QueuePush(nonEmpty,x);
}
4.出栈, 还是假设法, 找到不为空的队列, 然后通过为空的队列导一下,不要忘记找到数据之后, 让最后一个数据出队列.
int myStackPop(MyStack* obj) {assert(obj);Queue* Empty = &obj->q1;Queue* nonEmpty = &obj->q2;if(QueueEmpty(&obj->q2)){Empty = &obj->q2;nonEmpty = &obj->q1;}//把不为空的队列的数据的前n-1个数据导入到为空的队列while(QueueSize(nonEmpty)>1){QueuePush(Empty,QueueFront(nonEmpty));QueuePop(nonEmpty);}int top = QueueTail(nonEmpty);QueuePop(nonEmpty);return top;
}
5.剩下的几个方法总体来说比较简单, 代码如下,注意销毁操作, 我们手动开辟的空间都需要手动释放.
int myStackTop(MyStack* obj) {assert(obj);if(!QueueEmpty(&obj->q1)){return QueueTail(&obj->q1);}else{return QueueTail(&obj->q2);}}bool myStackEmpty(MyStack* obj) {return (QueueEmpty(&obj->q1)&&QueueEmpty(&obj->q2));
}void myStackFree(MyStack* obj) {assert(obj);QueueDestroy(&obj->q1);QueueDestroy(&obj->q2);free(obj);
}
完整代码
typedef int DataType;typedef struct QueueNode
{struct QueueNode* next;DataType val;
}QNode;typedef struct Queue
{QNode* phead;QNode* ptail;int size;
}Queue;void QueueInit(Queue* pq)
{assert(pq);pq->phead = NULL;pq->ptail = NULL;pq->size = 0;
}void QueueDestroy(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 QueuePush(Queue* pq, DataType x)
{assert(pq);QNode* newnode = (QNode*)malloc(sizeof(QNode));if (newnode == NULL){perror("malloc fail!");//perror函数在<stdio.h>头文件包含,标准错误流return;}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!=NULL);//条件为真,程序继续assert(pq->size!=0); //条件为真,程序继续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;
}int QueueSize(Queue* pq)
{assert(pq);return pq->size;
}DataType QueueFront(Queue* pq)
{assert(pq);assert(pq->phead);return pq->phead->val;
}DataType QueueTail(Queue* pq)
{assert(pq);assert(pq->ptail);return pq->ptail->val;
}
typedef struct {Queue q1;Queue q2;
} MyStack;MyStack* myStackCreate() {MyStack* s = (MyStack*)malloc(sizeof(MyStack));QueueInit(&s->q1);QueueInit(&s->q2);return s;
}void myStackPush(MyStack* obj, int x) {assert(obj);//假设法Queue* Empty = &obj->q1;Queue* nonEmpty = &obj->q2;if(QueueEmpty(&obj->q2)){Empty = &obj->q2;nonEmpty = &obj->q1;}//把数据插入到不为空的队列QueuePush(nonEmpty,x);
}int myStackPop(MyStack* obj) {assert(obj);Queue* Empty = &obj->q1;Queue* nonEmpty = &obj->q2;if(QueueEmpty(&obj->q2)){Empty = &obj->q2;nonEmpty = &obj->q1;}//把不为空的队列的数据的前n-1个数据导入到为空的队列while(QueueSize(nonEmpty)>1){QueuePush(Empty,QueueFront(nonEmpty));QueuePop(nonEmpty);}int top = QueueTail(nonEmpty);QueuePop(nonEmpty);return top;
}int myStackTop(MyStack* obj) {assert(obj);if(!QueueEmpty(&obj->q1)){return QueueTail(&obj->q1);}else{return QueueTail(&obj->q2);}}bool myStackEmpty(MyStack* obj) {return (QueueEmpty(&obj->q1)&&QueueEmpty(&obj->q2));
}void myStackFree(MyStack* obj) {assert(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);
*/