思路:
问题:
注意:取栈顶元素的时候不出栈,也有意外这把size-1个元素导入到另一个队列中,就会导致这两个队列都不为空,但是在我们两个队列实现栈的操作中,我们有一个前提就是必须保证至少有一个队列为空。
代码:
typedef int QDataType;
//定义队列节点的结构
typedef struct QueueNode
{
//数据
QDataType data;
//指向下一个节点的指针
struct QueueNode* next;
}QueueNode;
//定义队列的结构
typedef struct Queue
{
//指向队列对头的节点
QueueNode* phead;
//指向队列队尾的节点
QueueNode* ptail;
//保存队列中有效元素个数
int size;
}Queue;
//初始化队列
void QueueInit(Queue* pq)
{
//不能传空指针
assert(pq);
//将phead和ptail都置为空,表示这是一个空的队列
pq->phead = pq->ptail = NULL;
//将队列有效元素个数置为0
pq->size = 0;
}
// 入队列,队尾
void QueuePush(Queue* pq, QDataType x)
{
assert(pq);
//申请新的节点
QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
//判断malloc的返回值是否为空
if (newnode == NULL)
{
//反正值为空打印错误信息,退出
perror("malloc error!\n");
exit(1);
}
//为新申请的节点的data赋值
newnode->data = x;
//将新申请的节点的next指针置为空
newnode->next = NULL;
//处理非空队列和空队列两种情况
if (pq->phead == NULL)
{
//队列为空时新节点既是头节点也是尾节点
pq->phead = pq->ptail = newnode;
}
else
{
//队列不为空
//将新节点插入到ptaild的next位置
pq->ptail->next = newnode;
//将ptail指向新的节点,让新的节点变成尾节点
pq->ptail = newnode;
//下面这种和上面的效果一样pq->ptail->next位置就是ptail
//pq->ptail = pq->ptail->next;
}
//有效元素个数自增
pq->size++;
}
//队列判空
//返回类型是布尔类型,一定要加头文件stdbool.h
bool QueueEmpty(Queue* pq)
{
//不能传空指针
assert(pq);
//当头节点为空的时候,就说明队列为空,然后将false取反就为true。
//return !pq->phead;
return pq->phead == NULL && pq->ptail == NULL;
}
// 出队列,队头
void QueuePop(Queue* pq)
{
//不能传空指针以及队列不能为空
assert(pq && !QueueEmpty(pq));
//处理只有一个节点的情况,避免ptail变成野指针
if (pq->phead == pq->ptail)
{
free(pq->phead);
pq->phead = pq->ptail = NULL;
}
else//处理有多个节点的情况
{
//出队列是从队头出
//保存要出队的节点
QueueNode* del = pq->phead;
//phead指向下一个节点
pq->phead = pq->phead->next;
//释放要删除的节点
free(del);
del = NULL;
}
//有效元素个数自减
pq->size--;
}
//取队头数据
QDataType QueueFront(Queue* pq)
{
//不能传空指针以及队列不能为空
assert(pq );
assert(!QueueEmpty(pq));
//直接返回第一个节点的data数据
return pq->phead->data;
}
//取队尾数据
QDataType QueueBack(Queue* pq)
{
//不能传空指针以及队列不能为空
assert(pq && !QueueEmpty(pq));
//直接返回尾节点的data数据
return pq->ptail->data;
}
//队列有效元素个数
int QueueSize(Queue* pq)
{
//不能传空指针
assert(pq);
//返回有效元素个数
return pq->size;
}
//销毁队列
void QueueDestroy(Queue* pq)
{
//不能传空指针
assert(pq);
//遍历队列,释放节点
QueueNode* pcur = pq->phead;
//保存第二个节点
QueueNode* next = pq->phead;
//pcur为空时说明所以节点释放完成
while (pcur)
{
//保存下一个节点
next = pcur->next;
//释放当前节点
free(pcur);
//pcur走向下一个节点
pcur = next;
}
//指向队头和队尾的指针置为空
pq->phead = pq->ptail = NULL;
//将队列有效元素个数置0
pq->size = 0;
}
/
//两个队列来实现
typedef struct {
Queue q1;
Queue q2;
} MyStack;
//对栈的初始化函数
MyStack* myStackCreate() {
//申请空间
MyStack* ptr = (MyStack*)malloc(sizeof(MyStack));
//初始化两个队列
QueueInit(&ptr->q1);
QueueInit(&ptr->q2);
return ptr;
}
//入栈
void myStackPush(MyStack* obj, int x) {
//插入数据,哪里队列不为空往哪个队列里面插入
if(!QueueEmpty(&obj->q1))
{
QueuePush(&obj->q1,x);
}
else
{
QueuePush(&obj->q2,x);
}
}
//出栈
int myStackPop(MyStack* obj) {
//找不为空的队列
//假设q2为非空的队列,q1为空队列
Queue* empQ = &obj->q1;
Queue* noneQ = &obj->q2;
//判断是否为空队列
if(!QueueEmpty(&obj->q1))
{
empQ = &obj->q2;
noneQ = &obj->q1;
}
//将非空队列中的size-1的数据导入到空队列中
while(QueueSize(noneQ) > 1)
{
int front = QueueFront(noneQ);
//循环导入数据
QueuePush(empQ,front);
//出队列
QueuePop(noneQ);
}
//非空队列中剩下的一个元素就是要出栈的数据
int pop = QueueFront(noneQ);
//出队列
QueuePop(noneQ);
//返回数据
return pop;
}
//取栈顶元素 - 取非空队列中的队尾
int myStackTop(MyStack* obj) {
//找非空队列
if(QueueEmpty(&obj->q1))
{
return QueueBack(&obj->q2);
}
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);
obj = NULL;
}
/**
* 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);
*/
提交结果: