具备教学意义的实操(用队列实现栈)-CSDN博客https://blog.csdn.net/Jason_from_China/article/details/138729955
具备教学意义的实操(用栈实现队列)
题目
逻辑
核心逻辑
代码
#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
结构体的内存。