下面是一些思路分析和代码分享,有需要借鉴即可。
1.问题描述
我想用队列来实现栈的功能,具体而言是用两个队列做底层做出栈的功能来。
有人可能会疑问会不会多次一举,这里仅作练习,为了更加进一步了解栈/队列的性质
2.思路分析
一个栈模拟入队列,一个栈模拟出队列,出队列时直接弹出模拟出队列栈的栈顶元素,当该栈为空时,将模拟入队列栈中所有元素导入即可,不是每次都需要导入元素
3.下面是代码示例
c
#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
完。