使用两个队列实现先入后出的栈,并且支持栈的插入删除、获取栈顶元素、检查是否空栈的功能。
思路
两个队列实现栈的思路:所有数据插入在非空的队列队尾,另一个队列用于删除时的倒数据,将size-1个数据倒入到空队列2,最后一个数据即栈顶数据就在队列1的队头,进行保留并删除即可。
栈结构体创建
结构体包含两个队列q1、q2:
typedef struct {
Queue q1;
Queue q2;
} MyStack;
栈空间的创建以及栈结构体内两个队列成员的初始化
MyStack* myStackCreate() {
MyStack* ms = (MyStack*)malloc(sizeof(MyStack));
QueueInit(&ms->q1);
QueueInit(&ms->q2);
return ms;
}
两个队列实现栈的插入操作实现
在非空的队列中插入:
void myStackPush(MyStack* obj, int x) {
if(!QueueEmpty(&obj->q1))
QueuePush(&obj->q1,x);
else
QueuePush(&obj->q2,x);
}
两个队列实现栈的删除操作实现
使用假设判断法,创建nonemptyq和emptyq两个队列指针,先使nonemptyq指向q1,再使用if判断,如果q1为空,将nonemptyq指向q2并将emptyq指向q1,后面操作nonemptyq与emptyq指针即可。
删除操作,将nonemptyq指向队列中的前size-1个数据倒入emptyq指向的队列中,再将nonemptyq中最后一个数据获取并删除。
int myStackPop(MyStack* obj) {
Queue* nonemptyq = &obj->q1;
Queue* emptyq = &obj->q2;
if(QueueEmpty(&obj->q1))
{
nonemptyq = &obj->q2;
emptyq = &obj->q1;
}
while(QueueSize(nonemptyq)>1)
{
QueuePush(emptyq,QueueFront(nonemptyq));
QueuePop(nonemptyq);
}
int tmp = QueueFront(nonemptyq);
QueuePop(nonemptyq);
return tmp;
}
获取栈顶数据
即非空队列队尾数据的获取:
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);
obj=NULL;
}
整体代码如下:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
//队列---先进先出,FIFO
//队尾进,队头出
//队列的实现用什么?--->链表,单链表与双向链表都行
//不用数组,为什么?--->因为数组尾插虽然方便,但是头删很麻烦
//单链表也不好进行尾插,但是我们可以创建结构体Queue包含尾结点和头结点
#define QueueDataType int
typedef struct QueueNode
{
QueueDataType val;
struct QueueNode* next;
}QNode;
typedef struct Queue
{
QNode* phead;//头
QNode* ptail;//尾
int size;//记录队列数据个数
}Queue;
//初始化
void QueueInit(Queue* pq);
//销毁
void QueueDestroy(Queue* pq);
//插入
void QueuePush(Queue* pq, QueueDataType x);
//删除
void QueuePop(Queue* pq);
//获取队列头部元素
QueueDataType QueueFront(Queue* pq);
//获取队列尾部元素
QueueDataType QueueBack(Queue* pq);
//获取队列有效元素个数
int QueueSize(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* cur = pq->phead;
while (cur)
{
QNode* next = cur->next;
//pq->phead = pq->phead->next;//不直观
free(cur);
cur = next;
}
pq->phead = pq->ptail = NULL;
pq->size = 0;
pq = NULL;
}
//插入
void QueuePush(Queue* pq, QueueDataType x)
{
assert(pq);
//创建插入的结点newnode
QNode* newnode = (QNode*)malloc(sizeof(QNode));
if (newnode == NULL)
{
perror("malloc fail");
exit(-1);
}
newnode->next = NULL;
newnode->val = x;
//插入
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);
assert(pq->phead);//无结点
//写麻烦了
//QNode* cur = pq->phead;
//if (pq->ptail == pq->phead)//1个结点
//{
// free(cur);
// pq->phead = pq->ptail = cur = NULL;
//}
//else
//{
// //多个结点
// QNode* next = cur->next;
// free(cur);
// cur = NULL;
// pq->phead = next;
//}
QNode* cur = pq->phead;
QNode* next = cur->next;
free(cur);
cur = NULL;
pq->phead = next;
if (pq->phead == NULL)
pq->ptail = NULL;
pq->size--;
}
//获取队列头部元素
QueueDataType QueueFront(Queue* pq)
{
assert(pq);
assert(pq->phead);
return pq->phead->val;
}
//获取队列尾部元素
QueueDataType QueueBack(Queue* pq)
{
assert(pq);
assert(pq->phead);
return pq->ptail->val;
}
//获取队列有效元素个数
int QueueSize(Queue* pq)
{
assert(pq);
return pq->size;
}
//检测队列是否为空
bool QueueEmpty(Queue* pq)
{
assert(pq);
return pq->phead == NULL;
}
typedef struct {
Queue q1;
Queue q2;
} MyStack;
MyStack* myStackCreate() {
MyStack* ms = (MyStack*)malloc(sizeof(MyStack));
QueueInit(&ms->q1);
QueueInit(&ms->q2);
return ms;
}
void myStackPush(MyStack* obj, int x) {
if(!QueueEmpty(&obj->q1))
QueuePush(&obj->q1,x);
else
QueuePush(&obj->q2,x);
}
int myStackPop(MyStack* obj) {
Queue* nonemptyq = &obj->q1;
Queue* emptyq = &obj->q2;
if(QueueEmpty(&obj->q1))
{
nonemptyq = &obj->q2;
emptyq = &obj->q1;
}
while(QueueSize(nonemptyq)>1)
{
QueuePush(emptyq,QueueFront(nonemptyq));
QueuePop(nonemptyq);
}
int tmp = QueueFront(nonemptyq);
QueuePop(nonemptyq);
return tmp;
}
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);
obj=NULL;
}