做该种题要记住两个关键点:
一个队列用来插入数据。一个队列用来存数据1.空队列用来导数据
2.非空队列用来插入数据我们知道队列的特点:先进先出,只能在一端插入,一端删除。
而栈的特点是:先进后出,后进先出。
比如要让两个队列实现栈的功能,就拿出栈来说,如果要应该将栈顶元素5拿走。
但在队列1中,因为只能在队头进行删除,所以只能拿走元素1.
那该怎么办呢?要想pop掉队列中的元素5,我们得想办法将它搞成队头元素才行,这样才可以删除掉它。而如果队列2是空队列的话,那么我们这样做:将元素5之前的4个元素都放到队列2中,队列1中就只剩下元素5了,那元素5就相当于队头元素,就可以进行pop操作最终将其删除掉了,删除后队列1又变成空队列了。
而队列2就是非空队列。而重复这样的操作就可以实现删除栈顶元素的操作了:首先将非空队列中前n-1个元素导入空队列中,然后再pop掉非空队列中的元素。
完整代码:
typedef int QDataType;
typedef struct QueueNode{
struct QueueNode*next;
QDataType val;
}QNode;
typedef struct Queue{
QNode*phead;
QNode*ptail;
int size;
}Queue;
//初始化队列
void QueueInit(Queue*pq){
assert(pq);
pq->phead=pq->ptail=NULL;
pq->size=0;
}
//销毁队列
void QueueDestroy(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;
}
//队尾插入
void QueuePush(Queue*pq,QDataType x){
assert(pq);
QNode*newnode=(QNode*)malloc(sizeof(QNode));
if(newnode==NULL){
perror("malloc fail");
return;
}
newnode->next=NULL;
newnode->val=x;
if(pq->ptail==NULL){
pq->ptail=pq->phead=newnode;
}
else{
pq->ptail->next=newnode;
pq->ptail=newnode;
}
pq->size++;
}
//队头删除
void QueuePop(Queue*pq){
assert(pq);
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--;
}
//取队头队尾
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;
}
//取队长度
int QueueSize(Queue*pq){
assert(pq);
return pq->size;
}
bool QueueEmpty(Queue*pq){
assert(pq);
return pq->size==0;
}
typedef struct {
Queue q1;
Queue q2;
} MyStack;
MyStack* myStackCreate() {
MyStack*pst=(MyStack*)malloc(sizeof(MyStack));
QueueInit(&(pst->q1));
QueueInit(&(pst->q2));
return pst;
}
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))){
nonempty=&(obj->q1);
empty=&(obj->q2);
}
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) {
QueueDestroy(&(obj->q1));
QueueDestroy(&(obj->q2));
free(obj);
}