🎬 鸽芷咕:个人主页 🔥个人专栏:《Linux深造日志》《C++干货基地》
⛺️生活的理想,就是为了理想的生活!
🌈hello! 各位铁铁们大家好啊,不知道大家对栈和队列的学习都学过了吧?那么用栈来实现队列你会做嘛? ⛳️栈和队列我们前面说了都是一种特殊的线性表,而在学习过程中用栈来尝试实现队列是很有必要来考验一下我们对栈和队列的掌握的! 📚本期文章收录在《数据结构&算法》,大家有兴趣可以看看呐! ⛺️ 欢迎铁汁们 ✔️ 点赞 👍 收藏 ⭐留言 📝!
栈的特点是后进先出而我们要实现的队列是先进先出,诶这刚好和队列的特点相反:
先进先出的特点
了?前面说了使用俩个栈来解决队列先进先出的问题,其核心思想就是
那么具体的核心思想是什么?其实只需要把push的 翻转一下然后插入到pop 栈中就好了,这样我们就可以的到一个理论上先进先出的队列了。
pop
的时候都拿翻转完了之后的栈pop
没有数据了就继续从 push 里面翻转导入数据。核心思路我们有了接下来就是如何实现了,插入和删除解决了。其他问题那就不是问题非常简单就解决了,下面我们来看看把!
初始化和以前一样既然需要俩个栈来模拟实现队列,那么就需要俩个指针来管理栈区就够了:
malloc
就好了。malloc
的空间。📚 代码演示:
typedef struct {
ST pushst;
ST popst;
} MyQueue;
MyQueue* myQueueCreate() {
MyQueue* new = (MyQueue*)malloc(sizeof(MyQueue));
STInit(&new->pushst);
STInit(&new->popst);
return new;
}
判空这就巨简单了,既然我们用了俩个栈来实现队列那么只要这俩个栈都为空不就行了。
STEmpty(&obj->pushst) && STEmpty(&obj->popst)
📚 代码演示:
bool myQueueEmpty(MyQueue* obj) {
return STEmpty(&obj->pushst) && STEmpty(&obj->popst);
}
插入这个就是最简单的了,直接往push栈里面插入就好了:
📚 代码演示:
void myQueuePush(MyQueue* obj, int x) {
STPush(&obj->pushst,x);
}
删除队列就是我们前面的思想:
📚 代码演示:
int myQueuePop(MyQueue* obj) {
if(STEmpty(&obj->popst))
{
while(STSize(&obj->pushst))
{
STPush(&obj->popst,STTop(&obj->pushst));
STPop(&obj->pushst);
}
}
int top = STTop(&obj->popst);
STPop(&obj->popst);
return top;
}
头元素的的访问就很简单了,我们 pop 栈的第一个栈顶元素就是头元素:
📚 代码演示:
int myQueuePeek(MyQueue* obj) {
if(STEmpty(&obj->popst))
{
while(STSize(&obj->pushst))
{
STPush(&obj->popst,STTop(&obj->pushst));
STPop(&obj->pushst);
}
}
return STTop(&obj->popst);
}
销毁还是和以前一样,把malloc的空间都销毁:
📚 代码演示:
void myQueueFree(MyQueue* obj) {
STDestroy(&obj->pushst);
STDestroy(&obj->popst);
free(obj);
}
好了以上就是栈实现队列的全过程了:
📚 代码演示:
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
//#define N 10
//struct Stack
//{
// int a[N];
// int top;
//};
typedef int STDataType;
typedef struct Stack
{
STDataType* a;
int top;
int capacity;
}ST;
void STInit(ST* ps);
void STDestroy(ST* ps);
void STPush(ST* ps, STDataType x);
void STPop(ST* ps);
STDataType STTop(ST* ps);
int STSize(ST* ps);
bool STEmpty(ST* ps);
void STInit(ST* ps)
{
assert(ps);
ps->a = NULL;
ps->capacity = 0;
ps->top = 0;
}
void STDestroy(ST* ps)
{
assert(ps);
free(ps->a);
ps->a = NULL;
ps->top = ps->capacity = 0;
}
void STPush(ST* ps, STDataType x)
{
assert(ps);
// 11:40
if (ps->top == ps->capacity)
{
int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
STDataType* tmp = (STDataType*)realloc(ps->a, sizeof(STDataType) * newCapacity);
if (tmp == NULL)
{
perror("realloc fail");
exit(-1);
}
ps->a = tmp;
ps->capacity = newCapacity;
}
ps->a[ps->top] = x;
ps->top++;
}
void STPop(ST* ps)
{
assert(ps);
//
assert(ps->top > 0);
--ps->top;
}
STDataType STTop(ST* ps)
{
assert(ps);
//
assert(ps->top > 0);
return ps->a[ps->top - 1];
}
int STSize(ST* ps)
{
assert(ps);
return ps->top;
}
bool STEmpty(ST* ps)
{
assert(ps);
return ps->top == 0;
}
typedef struct {
ST pushst;
ST popst;
} MyQueue;
MyQueue* myQueueCreate() {
MyQueue* new = (MyQueue*)malloc(sizeof(MyQueue));
STInit(&new->pushst);
STInit(&new->popst);
return new;
}
void myQueuePush(MyQueue* obj, int x) {
STPush(&obj->pushst,x);
}
int myQueuePop(MyQueue* obj) {
if(STEmpty(&obj->popst))
{
while(STSize(&obj->pushst))
{
STPush(&obj->popst,STTop(&obj->pushst));
STPop(&obj->pushst);
}
}
int top = STTop(&obj->popst);
STPop(&obj->popst);
return top;
}
int myQueuePeek(MyQueue* obj) {
if(STEmpty(&obj->popst))
{
while(STSize(&obj->pushst))
{
STPush(&obj->popst,STTop(&obj->pushst));
STPop(&obj->pushst);
}
}
return STTop(&obj->popst);
}
bool myQueueEmpty(MyQueue* obj) {
return STEmpty(&obj->pushst) && STEmpty(&obj->popst);
}
void myQueueFree(MyQueue* obj) {
STDestroy(&obj->pushst);
STDestroy(&obj->popst);
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);
*/
☁️ 好了以上就是栈的实现队列的全部解析了,总的来说只要掌握技巧就不难呢!核心思想掌握了那就直接秒杀.
看到这里了还不给博主扣个:
⛳️ 点赞
☀️收藏
⭐️ 关注
!
💛 💙 💜 ❤️ 💚💓 💗 💕 💞 💘 💖
拜托拜托这个真的很重要!
你们的点赞就是博主更新最大的动力!
有问题可以评论或者私信呢秒回哦。