具备教学意义的实操(用队列实现栈)-CSDN博客https://blog.csdn.net/Jason_from_China/article/details/138729955
具备教学意义的实操(用栈实现队列)
题目
232. 用栈实现队列 - 力扣(LeetCode)
逻辑
核心逻辑
代码
#include<stdio.h> #include<assert.h> #include<stdlib.h> typedef int STDataType; typedef struct Stack {STDataType* _a; // 首元素的地址int _top; // 栈顶,初始化为0,也就是等同于size,初始化为-1,等同于下标int _capacity; // 容量 }Stack; // 初始化栈 void StackInit(Stack* ps); // 销毁栈 void StackDestroy(Stack* ps); // 入栈 void StackPush(Stack* ps, STDataType data); // 出栈 void StackPop(Stack* ps); // 获取栈顶元素 STDataType StackTop(Stack* ps); // 获取栈尾元素 STDataType StackTail(Stack* ps); // 获取栈中有效元素个数 int StackSize(Stack* ps); // 检测栈是否为空,如果为空返回非零结果,如果不为空返回0 int StackEmpty(Stack* ps); // 初始化栈 void StackInit(Stack* ps) {ps->_a = NULL;// 这里栈顶初始化为-1和初始化为0是不一样的// 0 0 0 0 0 0 0 0 数组// -1 0 0 0 0 0 0 0 0 初始化为-1// 0 0 0 0 0 0 0 0 初始化为0// 初始化为0,也就是等同于size,初始化为-1,等同于下标ps->_capacity = ps->_top = 0; } //销毁 void StackDestroy(Stack* ps) {if (ps != NULL) { // 检查指针是否非空free(ps->_a);ps->_a = NULL;ps->_capacity = 0;ps->_top = -1; // 将栈顶指针设置为-1,表示栈为空} } // 入栈 void StackPush(Stack* ps, STDataType data) {//首先判断容量是多少,然后进行扩容if (ps->_capacity == ps->_top){//扩容int newapacity = ps->_capacity == 0 ? 4 : 2 * ps->_capacity;STDataType* tmp = (STDataType*)realloc(ps->_a, newapacity * sizeof(STDataType));if (tmp == NULL){perror("StackPush:tmp:error:");exit(1);}//改变容量大小,指向新空间的头第一个元素位置的地址ps->_capacity = newapacity;ps->_a = tmp;}//插入数值ps->_a[ps->_top] = data;ps->_top++; } // 出栈 void StackPop(Stack* ps) {// 判断为不为空,判断里面有没有数值assert(ps && ps->_top);ps->_top--; } // 获取栈顶元素 STDataType StackTop(Stack* ps) {assert(ps && ps->_top >= 0);return ps->_a[ps->_top-1]; } // 获取栈尾元素 STDataType StackTail(Stack* ps) {assert(ps && ps->_top);return ps->_a[0]; } // 获取栈中有效元素个数 int StackSize(Stack* ps) {assert(ps && ps->_top);return ps->_top - 1; } // 检测栈是否为空,如果为空返回非零结果(1),如果不为空返回0 int StackEmpty(Stack* ps) {assert(ps);return ps->_top == 0;// 所以,ps->_top == 0 这个表达式的作用是比较栈顶位置 ps->_top 是否等于 0。// 如果相等,说明栈为空,表达式结果为 true(在C语言中用 1 表示);// 如果不相等,说明栈不为空,表达式结果为 false(在C语言中用 0 表示) }typedef struct { Stack Q1;Stack Q2; } MyQueue;//初始化 MyQueue* myQueueCreate() { MyQueue* ps = (MyQueue*)malloc(sizeof(MyQueue));if(ps == NULL){perror("ps");exit(1);}StackInit(&(ps->Q1));StackInit(&(ps->Q2));return ps; } //入数据 void myQueuePush(MyQueue* obj, int x) { StackPush(&(obj->Q1),x); }//获取栈顶数据 int myQueuePeek(MyQueue* obj) {//队列是先进后出,栈是先进先出if(StackEmpty(&(obj->Q2))){while(!StackEmpty(&(obj->Q1))){StackPush(&(obj->Q2),StackTop(&(obj->Q1)));StackPop(&(obj->Q1));}}return StackTop(&(obj->Q2)); } //删除栈顶数据 int myQueuePop(MyQueue* obj) {int ret = myQueuePeek(obj);StackPop(&(obj->Q2));return ret; } //判空 bool myQueueEmpty(MyQueue* obj) {return StackEmpty(&(obj->Q1)) && StackEmpty(&(obj->Q2)); } //释放 void myQueueFree(MyQueue* obj) {StackDestroy(&(obj->Q1));StackDestroy(&(obj->Q2));free(obj); } /*** Your MyQueue struct will be instantiated and called as such:* MyQueue* obj = myQueueCreate();* myQueuePush(obj, x);* int param_2 = myQueuePop(obj);* int param_3 = myQueuePeek(obj);* bool param_4 = myQueueEmpty(obj);* myQueueFree(obj); */
代码解释
StackInit: 初始化一个栈,设置栈的容量和栈顶指针为0,同时初始化栈的数组为NULL。
StackDestroy: 销毁栈,释放栈的内存,并将栈的指针和容量设置为0,栈顶指针设置为-1。
StackPush: 向栈中压入一个元素。如果栈的容量等于栈顶指针(意味着栈已满),则先进行扩容,然后将数据压入栈顶。
StackPop: 从栈中弹出一个元素。由于栈顶指针指向栈顶元素的下一个位置,所以直接减少栈顶指针的值。
StackTop: 返回栈顶元素的值,但不移除它。
StackTail: 返回栈尾元素的值,但不移除它。
StackSize: 返回栈中元素的数量。
StackEmpty: 判断栈是否为空,如果栈顶指针为0,表示栈为空。
myQueueCreate: 创建并初始化队列,分配内存给
MyQueue
结构体,并初始化其两个栈Q1
和Q2
。myQueuePush: 向队列中添加一个元素。由于队列使用栈
Q1
来模拟入队操作,所以直接将元素压入Q1
。myQueuePeek: 返回队列的第一个元素,即队列的前端元素。由于队列是先进先出的,而栈是先进后出的,所以如果出队栈
Q2
为空,需要将Q1
中的所有元素依次弹出并压入Q2
,这样Q2
的底部就成为队列的前端。然后返回Q2
的栈顶元素。myQueuePop: 移除并返回队列的第一个元素。它首先调用
myQueuePeek
获取队列前端的元素,然后调用StackPop
从Q2
中移除该元素,并返回它。myQueueEmpty: 判断队列是否为空。如果
Q1
和Q2
都为空,则队列为空。myQueueFree: 释放队列占用的内存,销毁两个栈,释放
MyQueue
结构体的内存。