😶🌫️Take your time ! 😶🌫️
💥个人主页:🔥🔥🔥大魔王🔥🔥🔥
💥代码仓库:🔥🔥魔王修炼之路🔥🔥
💥所属专栏:🔥魔王的修炼之路–数据结构🔥
如果你觉得这篇文章对你有帮助,请在文章结尾处留下你的点赞👍和关注💖,支持一下博主。同时记得收藏✨这篇文章,方便以后重新阅读。
文章目录
- 一、题目
- 二、思路
- 三、代码
- 1、导入实现栈的代码
- 2、创建模拟队列的栈
- 3、入队列
- 4、出队列
- 5、窥探队列开头元素
- 6、判空
- 7、释放
- 四、总结
一、题目
力扣链接
二、思路
栈是后进先出,队列是先进先出。
用两个栈模拟队列,因为栈后进先出,所以从一个栈导到另一个栈会颠倒顺序,所以我们固定两个栈的作用,一个为出,一个为进,入的话就入到进栈的栈里,出的话如果出栈的栈不为空就直接出,否则让进栈的栈导入到出栈的栈中(不理解原理简单画个图就懂了)。
三、代码
1、导入实现栈的代码
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
typedef int STDateType;
typedef struct Stack
{
STDateType* a;
int top;//如果初始化为0,可以理解为元素个数(也就是栈顶元素下标+1),如果初始化为-1,可以理解为栈顶元素的下标
int capacity;
}ST;
//初始化和最后销毁
void STInit(ST* ps);
void STDestory(ST* ps);
//入栈
void STPush(ST* ps, STDateType x);
//出栈
void STPop(ST* ps);
//元素个数
int STSize(ST* ps);
//判断是否为空
bool STEmpty(ST* ps);
//栈顶元素
STDateType STTop(ST* ps);
//初始化和最后销毁
void STInit(ST* ps)
{
assert(ps);
//ps->a = malloc(sizeof(ST) * 5); 1.没有强转
ps->a = (STDateType*)malloc(sizeof(ST) * 5);
2.开辟新空间后没有检查
if (ps->a == NULL)
{
perror("malloc fail");
return;
}
ps->top = 0;
ps->capacity = 5;
}
void STDestory(ST* ps)
{
assert(ps);
free(ps->a);
ps->capacity = 0;
ps->a = NULL;
1.没有让top也就是栈顶位置重置。
ps->top = 0;
//最后在Test.c上让结构体指针指向空。
}
//入栈
void STPush(ST* ps, STDateType x)
{
assert(ps);
//if (ps->top == ps->capacity)
//{
// ST* str = realloc(ps->a, ps->capacity * sizeof(ST) * 2);
// if (str == NULL)
// {
// perror("realloc fail");
// return;
// }
//}
1.没有把扩容的时候创建的新指针赋给原指针
if (ps->top == ps->capacity) //判断是否满了
{
//ST* temp = realloc(ps->a, ps->capacity * sizeof(ST) * 2);
//2.指针应该指向数据的类型的地址,而且realloc也没强转为数据类型的指针
STDateType* temp = (STDateType*)realloc(ps->a, ps->capacity * sizeof(ST) * 2);
if (temp == NULL)
{
perror("realloc fail");
return;
}
else
{
ps->a = temp;
3.忘记让结构体内的容量*2
ps->capacity *= 2;
temp = NULL;
}
}
ps->a[ps->top] = x;
ps->top++;
}
//出栈
void STPop(ST* ps)
{
assert(ps);
assert(!STEmpty(ps));
ps->top--;
}
//元素个数
int STSize(ST* ps)
{
assert(ps);
return ps->top;
}
//判断是否为空
bool STEmpty(ST* ps)
{
assert(ps);
return ps->top == 0;
}
//栈顶元素
STDateType STTop(ST* ps)
{
assert(ps);
assert(!STEmpty(ps));
return ps->a[ps->top - 1];
}
2、创建模拟队列的栈
创建一个结构体类型,里面放两个栈为成员,然后创建一个这个结构体变量并且初始化。
typedef struct {
ST PopStact;
ST PushStact;
} MyQueue;
MyQueue* myQueueCreate() {
MyQueue* create = (MyQueue*)malloc(sizeof(MyQueue));
if (create == NULL)
{
perror("malloc error");
assert(create);
}
STInit(&create->PopStact);
STInit(&create->PushStact);
return create;
}
3、入队列
直接入到专门入队列的栈里。
void myQueuePush(MyQueue* obj, int x) {
STPush(&obj->PushStact, x);
}
4、出队列
先出出数据的栈,如果没数据了就导一下。
int myQueuePop(MyQueue* obj) {
if (STEmpty(&obj->PopStact))
{
while (STSize(&obj->PushStact))
{
STPush(&obj->PopStact, STTop(&obj->PushStact));
STPop(&obj->PushStact);
}
}
int ret = STTop(&obj->PopStact);
STPop(&obj->PopStact);
return ret;
}
5、窥探队列开头元素
即出数据栈的栈顶元素,如果其没数据,那么就让入数据栈导入出数据栈,还是出数据栈的栈顶元素。也就是删除元素操作不删除该元素,只返回一下这个值。
int myQueuePeek(MyQueue* obj) {
if (STEmpty(&obj->PopStact))
{
while (STSize(&obj->PushStact))
{
STPush(&obj->PopStact, STTop(&obj->PushStact));
STPop(&obj->PushStact);
}
}
return STTop(&obj->PopStact);
}
6、判空
两个栈都为空即为空。
bool myQueueEmpty(MyQueue* obj) {
return STEmpty(&obj->PopStact) && STEmpty(&obj->PushStact);
}
7、释放
malloc了多少次释放多少次。
void myQueueFree(MyQueue* obj) {
STDestory(&obj->PushStact);
STDestory(&obj->PopStact);
free(obj);
}
四、总结
- 博主长期更新,博主的目标是不断提升阅读体验和内容质量,如果你喜欢博主的文章,请点个赞或者关注博主支持一波,我会更加努力的为你呈现精彩的内容。
🌈专栏推荐
😈魔王的修炼之路–C语言
😈魔王的修炼之路–数据结构初阶
😈魔王的修炼之路–C++
😈魔王的修炼之路–Linux
更新不易,希望得到友友的三连支持一波。收藏这篇文章,意味着你将永久拥有它,无论何时何地,都可以立即找到重新阅读;关注博主,意味着无论何时何地,博主将永久和你一起学习进步,为你带来有价值的内容。