栈与队列OJ题 --- 用栈实现队列

题目描述

有了上篇博客用队列实现栈的基础,这道题应该会容易一些

本质就是要 用两个 先进后出的 栈 来实现 队列的 先进先出的功能

思路形成~

我们直接来演示一下用栈模拟实现队列的先进先出的操作~~~

开始时两个栈均为空

入数据1 (两个栈为空,随便入一个即可~)

 

入数据2,3,4

出数据~

现在需要出数据了~,要实现的是队列的先进先出,1是最先进来的,因此我们现在需要出数据1

显然根据上道题的思路,我们需要捯数据,注意栈是后进先出~

 第一个栈只剩下1了,我们直接pop掉就可以

 

 继续出数据~

刚才把1pop掉了,现在如果想继续pop呢?根据队列先进先出原则,下来应该pop2,这时我们发现不需要捯数据了,2此时就在第二个栈的栈顶,直接从栈顶弹出即可~

所以从这步就可以看出,这道题和上道题实现思路是有差异的~

我们不妨这样,队列入数据都进第一个栈,队列出数据时如果第二个栈不为空,就直接从第二个栈出数据,如果第二个栈为空,就把第一个栈中的所有数据都捯到第二个栈后再出数据,总之出数据都从第二个栈出,我们分析一下这样是否可行~

现在接着上面的情况继续分析~~

现在又需要入数据5,6

根据我们的想法,直接让数据入第一个栈~

继续出数据

按照上面想法,出数据时第二个栈不为空,直接出数据~

 继续出数据~

按照上面想法,出数据时第二个栈为空,先把所有数据捯到第二个栈后再出数据~

 

 可以看到,入数据是1,2,3,4,5,6,出数据也是1,2,3,4,5,6,符合队列先进先出的特点,所以我们的想法是没有问题的

到这思路就厘清了~

最终思路:

定义两个栈,第一个栈叫pushst,就是专门用来入数据的,第二个栈叫popst, 专门用来出数据~

题目所给函数原型

代码实现

下面需要用到栈的相关操作,我们之前就已经实现过,直接把代码搬过来~

#include<stdio.h>
#include<stdbool.h>
#include<stdlib.h>
#include<assert.h>


typedef int STDataType;
typedef struct Stack
{
	STDataType* a;
	int top;  
	int capacity; 
}ST;

//栈初始化
void STInit(ST* pst);

//栈的销毁
void STDestory(ST* pst);

//压栈
void STPush(ST* pst,STDataType x);

//出栈
void STPop(ST* pst);

//获取栈顶元素
STDataType STTop(ST* pst);

//判空
bool STEmpty(ST* pst);

//获取size
int STSize(ST* pst);

//栈的初始化
void STInit(ST* pst)
{
	assert(pst);
	pst->a = NULL;

	pst->top = -1; //top指向栈顶元素
	pst->top = 0; //top指向栈顶元素的下一个位置
	pst->capacity = 0;
}


//栈的销毁
void STDestory(ST* pst)
{
	assert(pst);

	free(pst->a);
	pst->a = NULL;
	pst->top = pst->capacity = 0;
}


//压栈
void STPush(ST* pst, STDataType x)
{
	if (pst->top == pst->capacity)
	{
		int newCapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
		STDataType* tmp = realloc(pst->a, newCapacity * sizeof(STDataType));
		if (tmp == NULL)
		{
			perror("realloc fail\n");
			return;
		}
		pst->a = tmp;
		pst->capacity = newCapacity;
	}

	pst->a[pst->top] = x;
	pst->top++;
}


//出栈
void STPop(ST* pst)
{
	assert(pst);
	assert(!STEmpty(pst));
	pst->top--;
}


//获取栈顶元素
STDataType STTop(ST* pst)
{
	assert(pst);
	assert(!STEmpty(pst));
	return pst->a[pst->top - 1];
}


//判空
bool STEmpty(ST* pst)
{
	return pst->top == 0;
	//或者写成
	// return !(pst->top)
}


//获取栈中元素个数
int STSize(ST* pst)
{
	assert(pst);
	return pst->top;
}

这两个功能我们选择先实现第二个peek,然后在pop函数中就可以调用peek函数

①定义包含两个栈的队列的结构

typedef struct {
    ST popst;
    ST pushst;
} MyQueue;

 ②创建包含两个栈的队列

记着创建栈的同时对其初始化~

MyQueue* myQueueCreate() {
    MyQueue* obj = (MyQueue*)malloc(sizeof(MyQueue));
    if(obj == NULL)
    {
        perror("malloc");
        return NULL;
    }
    STInit(&obj->pushst);
    STInit(&obj->popst);
    return obj;
}

③队列入数据

只需要对于pushst进行压栈操作~


void myQueuePush(MyQueue* obj, int x) {
    STPush(&obj->pushst, x);
}

④返回队头元素

int myQueuePeek(MyQueue* obj) {
    if(STEmpty(&obj->popst))
    {
        while(!STEmpty(&obj->pushst))
        {
            STPush(&obj->popst, STTop(&obj->pushst));
            STPop(&obj->pushst);
        }
    }
    return STTop(&obj->popst);
}

这就是我们前面说的,pushst栈中有数据时,先捯到popst,再获取popst栈顶(队头)元素,pushst没有数据时,直接获取popst栈顶返回即可

⑤队头移除元素并返回

调用peek的好处就是如果popst中有数据,就可以直接把数据都捯过来,保证了popst的栈顶元素一定是队目前所有元素中最先进入的(队头元素)

int myQueuePop(MyQueue* obj) {
    int front = myQueuePeek(obj);
    STPop(&obj->popst);
    return front;
}

⑥判断队列是否为空

队列为空就是两个栈均为空~

bool myQueueEmpty(MyQueue* obj) {
    return STEmpty(&obj->pushst)
    && STEmpty(&obj->popst);
}

⑦销毁队列

不仅要释放掉队列,还要释放掉底层占据空间的两个栈哦~

void myQueueFree(MyQueue* obj) {
    STDestory(&obj->pushst);
    STDestory(&obj->popst);
    free(obj);
}

完整代码

#include<stdio.h>
#include<stdbool.h>
#include<stdlib.h>
#include<assert.h>


typedef int STDataType;
typedef struct Stack
{
	STDataType* a;
	int top;  
	int capacity; 
}ST;

//栈初始化
void STInit(ST* pst);

//栈的销毁
void STDestory(ST* pst);

//压栈
void STPush(ST* pst,STDataType x);

//出栈
void STPop(ST* pst);

//获取栈顶元素
STDataType STTop(ST* pst);

//判空
bool STEmpty(ST* pst);

//获取size
int STSize(ST* pst);

//栈的初始化
void STInit(ST* pst)
{
	assert(pst);
	pst->a = NULL;

	pst->top = -1; //top指向栈顶元素
	pst->top = 0; //top指向栈顶元素的下一个位置
	pst->capacity = 0;
}


//栈的销毁
void STDestory(ST* pst)
{
	assert(pst);

	free(pst->a);
	pst->a = NULL;
	pst->top = pst->capacity = 0;
}


//压栈
void STPush(ST* pst, STDataType x)
{
	if (pst->top == pst->capacity)
	{
		int newCapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
		STDataType* tmp = realloc(pst->a, newCapacity * sizeof(STDataType));
		if (tmp == NULL)
		{
			perror("realloc fail\n");
			return;
		}
		pst->a = tmp;
		pst->capacity = newCapacity;
	}

	pst->a[pst->top] = x;
	pst->top++;
}


//出栈
void STPop(ST* pst)
{
	assert(pst);
	assert(!STEmpty(pst));
	pst->top--;
}


//获取栈顶元素
STDataType STTop(ST* pst)
{
	assert(pst);
	assert(!STEmpty(pst));
	return pst->a[pst->top - 1];
}


//判空
bool STEmpty(ST* pst)
{
	return pst->top == 0;
	//或者写成
	// return !(pst->top)
}


//获取栈中元素个数
int STSize(ST* pst)
{
	assert(pst);
	return pst->top;
}


typedef struct {
    ST popst;
    ST pushst;
} MyQueue;


MyQueue* myQueueCreate() {
    MyQueue* obj = (MyQueue*)malloc(sizeof(MyQueue));
    if(obj == NULL)
    {
        perror("malloc");
        return NULL;
    }
    STInit(&obj->pushst);
    STInit(&obj->popst);
    return obj;
}

void myQueuePush(MyQueue* obj, int x) {
    STPush(&obj->pushst, x);
}

int myQueuePeek(MyQueue* obj) {
    if(STEmpty(&obj->popst))
    {
        while(!STEmpty(&obj->pushst))
        {
            STPush(&obj->popst, STTop(&obj->pushst));
            STPop(&obj->pushst);
        }
    }
    return STTop(&obj->popst);
}

int myQueuePop(MyQueue* obj) {
    int front = myQueuePeek(obj);
    STPop(&obj->popst);
    return front;
}


bool myQueueEmpty(MyQueue* obj) {
    return STEmpty(&obj->pushst)
    && STEmpty(&obj->popst);
}

void myQueueFree(MyQueue* obj) {
    STDestory(&obj->pushst);
    STDestory(&obj->popst);
    free(obj);
}

本篇 用栈实现队列题目 就分享到这啦,欢迎大家交流指正~

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值