下面是一些思路分析和代码分享,有需要借鉴即可。
1.问题描述
我想用队列来实现栈的功能,具体而言是用两个队列做底层做出栈的功能来。
有人可能会疑问会不会多次一举,这里仅作练习,为了更加进一步了解栈/队列的性质
2.思路分析
一个栈模拟入队列,一个栈模拟出队列,出队列时直接弹出模拟出队列栈的栈顶元素,当该栈为空时,将模拟入队列栈中所有元素导入即可,不是每次都需要导入元素
3.下面是代码示例
#include<stdio.h>
#include<stdbool.h>
#include<stdlib.h>
#include<assert.h>//队列结构-底层:单链表实现
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 QueueDestroy(Queue* pq);
int QueueSize(Queue* pq);
//插入与删除
void QueuePush(Queue* pq, QDataType x);
void QueuePop(Queue* pq);
//取头结点与取尾结点
QDataType QueueFront(Queue* pq);
QDataType QueueBack(Queue* pq);
bool QueueEmpty(Queue* pq);void QueueInit(Queue* pq)
{assert(pq);pq->phead = NULL;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;
}int QueueSize(Queue* pq)
{assert(pq);return pq->size;
}void QueuePush(Queue* pq, QDataType x)//=尾插
{assert(pq);//申请一块堆空间QNode* newnode = (QNode*)malloc(sizeof(QNode));if (newnode == NULL){perror("malloc fail");exit(1);}//新节点的初始化newnode->val = x;newnode->next = NULL;//如果是没有结点时候需要插入if (pq->phead == NULL){pq->phead = pq->ptail = newnode;}//至少有一个节点时需要插入(尾插)else{pq->ptail->next = newnode;pq->ptail = newnode;}pq->size++;
}void QueuePop(Queue* pq)
{assert(pq);//这里其实有三种不同的情况://1.没有结点,这种是不可以删除的//2.一个结点,那么就需要phead与ptail都需要调整(容易被坑)//3.多个结点,只需要调整phead即可assert(pq->phead != NULL);if (pq->phead == pq->ptail){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 != NULL);//有数据return pq->phead->val;
}QDataType QueueBack(Queue* pq)
{assert(pq);//没有数据,不能取出assert(pq->phead != NULL);//有数据return pq->ptail->val;
}bool QueueEmpty(Queue* pq)
{assert(pq);return pq->phead == NULL;
}//两个队列
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) {//把数据放入非空队列//q1非空,放入q1中if (!QueueEmpty(&obj->q1)){QueuePush(&obj->q1, x);}else//q2非空,放入q2中{QueuePush(&obj->q2, x);}
}int myStackPop(MyStack* obj) {//这个函数是一个重点,是删除函数,那么需要做的事情有把非空队列的前n-1项放到空队列中,删除非空队列的最后一个数字//找出非空队列与空队列的地址Queue* pEmptyQ = &obj->q1;Queue* pNoEmptyQ = &obj->q2;//如果q1为非空,则假设错误,所以交换一下if (!QueueEmpty(&obj->q1)){pEmptyQ = &obj->q2;pNoEmptyQ = &obj->q1;}//将非空队列中的前n-1个数据放入另一个空队列中while (QueueSize(pNoEmptyQ) > 1)//只要非空队列中剩余数据>=1,那么循环就一直进行{int front = QueueFront(pNoEmptyQ);//从非空队列中拿到第一个数字QueuePush(pEmptyQ, front);//把非空队列中的第一个数字交给空队列QueuePop(pNoEmptyQ);//删除非空队列中的第一个数字}int front = QueueFront(pNoEmptyQ);//从非空队列中拿出最后一个数字QueuePop(pNoEmptyQ);//删除非空队列中最后一个数字//返回return front;
}//这个函数只需要找出非空队列中最后一个数字就好
int myStackTop(MyStack* obj) {if (QueueEmpty(&obj->q1))//q1为空,拿出q2中的最后一个数字{return QueueBack(&obj->q2);}else//反之,如果q2为空,那么返回q1中最后一个数字{return QueueBack(&obj->q1);}
}bool myStackEmpty(MyStack* obj) {return QueueEmpty(&obj->q1) && QueueEmpty(&obj->q2);
}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);
*/
5.练习
力扣题目练习请点击:LINK
完。