栈与队列:用栈实现队列

目录

题目:

栈与队列的数据模型对比:

思路分析🎇:

代码分析: 

一、定义队列

二、初始化队列

三、入队

四、出队⭐

代码解析:

五、获取队头元素

六、查看队列是否为空

七、销毁队列

完整代码

需要手撕的栈的代码


题目:

请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(pushpoppeekempty)。


实现 MyQueue 类:

  • void push(int x) 将元素 x 推到队列的末尾
  • int pop() 从队列的开头移除并返回元素
  • int peek() 返回队列开头的元素
  • boolean empty() 如果队列为空,返回 true ;否则,返回 false

说明:

  • 你 只能 使用标准的栈操作 —— 也就是只有 push to toppeek/pop from topsize, 和 is empty 操作是合法的。
  • 你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。

题源:232. 用栈实现队列 - 力扣(LeetCode)

题目内容:

 

栈与队列的数据模型对比:

思路分析🎇:

本题的核心部分和原理是如何将栈的特点演变成队列的特点,即如何将演化栈的后进先出为队列的先进先出。

按照题目的要求,我们需要使用两个栈进行栈的实现,以此我们可以根据栈的特点,进行数据的传输,和复原来解决问题。

可参考方法:栈与队列:用队列实现栈-CSDN博客

  1. 如图所示,根据队列和栈的不同之处,以题目要求中只能通过出栈的方式来实现出队,所以我们需要对参考方法:栈与队列:用队列实现栈-CSDN博客进行改动。
  2. 因为出队出的是队头,所以根据数据模型对比,需要在栈上的实现是把栈底元素进行输出,于是将栈底元素进行保留,其他的元素通过获取栈底元素的函数以及入栈函数的方法,进入到另一个空的栈中。 
  3. 当然,进入到另一个栈后,表达的形式和原来的栈正好相反,所以为了防止以后不出错,必须再度以相同的方式回到原来的栈中,以此恢复以前的顺序

代码分析: 

一、定义队列

因为本题是需要使用两个栈来实现队列,于是需要对栈的调用,因此队列内部的定义只需要使用两个指向不同栈的指针即可。

二、初始化队列

使用之前定义的队列(MyQueue)创造一个空间,表示队列的创建,随后在这个空间的内部调用栈的初始化函数,对队列中的两个栈进行初始化。

三、入队

因为之前在思路分析中讲诉过出队需要经历,元素的交换、去除、二次交换,而在这些的过程中,入队是不会受到影响的,因为会进行元素顺序的恢复,所以入队的元素只需要插入进不为空的栈的后面即可

四、出队⭐

代码解析:

使用假设的方法,对空和不空的栈进行简化操作,方便之后的操作。

  • 在思路分析中说过,我们要把栈底元素留下,其余元素丢到另一个空的栈中,所以这里需要对栈内的元素有效个数进行判断,确保留下一个。
  • 之后的转移需要用到栈的获取栈底元素函数和入栈函数,进行以循环的方式不断地将每一次的栈底获取插入到"空栈"中。

  • 然后因为题目交给的代码是int类型,表示我们需要输出最后的栈顶也是最后的栈顶元素,并且删除,表示出队。

  • 最后,需要进行栈的复原,以免下次进行出队或则之后的入队操作会因为顺序的错乱而导致的问题。

五、获取队头元素

对于获取栈顶元素,其实就和出队的方式差不多,因为栈不像队列具有指向栈底的指针和对应的函数,于是我们还是需要对栈一步一步的将元素进行迁移,然后复原,且中途没有元素的删除部分。

六、查看队列是否为空

  • 需要两个栈同时为空才行!因为我们进行了互换操作!

七、销毁队列

  • 要分别把两个栈进行销毁后在销毁封存两个栈的指针的结构体

完整代码

需要手撕的栈的代码

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

typedef int STDataType;
typedef struct Stack
{
	STDataType* a;
	int top;		// 标识栈顶下一个位置
	int capacity;
}ST;
//栈的初始化
void STInit(ST* pst);
//栈的销毁
void STDestroy(ST* pst);
// 入栈
void STPush(ST* pst, STDataType x);
//出栈
void STPop(ST* pst);
//获取栈顶元素
STDataType STTop(ST* pst);
//检测栈是否为空
bool STEmpty(ST* pst);
//获取栈的有效元素个数
int STSize(ST* pst);

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

	pst->a = NULL;
	pst->capacity = 0;
	pst->top = 0;
}

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

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

// 入栈
void STPush(ST* pst, STDataType x)
{
	assert(pst);

	if (pst->top == pst->capacity)
	{
		int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
		STDataType* tmp = (STDataType*)realloc(pst->a, sizeof(STDataType) * newcapacity);
		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}

		pst->a = tmp;
		pst->capacity = newcapacity;
	}

	pst->a[pst->top] = x;
	pst->top++;
}
//出栈
void STPop(ST* pst)
{
	assert(pst);
	// 不为空
	assert(pst->top > 0);

	pst->top--;
}
//获取栈顶元素
STDataType STTop(ST* pst)
{
	assert(pst);
	// 不为空
	assert(pst->top > 0);

	return pst->a[pst->top - 1];
}
//检测栈是否为空
bool STEmpty(ST* pst)
{
	assert(pst);

	/*if (pst->top == 0)
	{
		return true;
	}
	else
	{
		return false;
	}*/

	return pst->top == 0;
}
//获取栈的有效元素个数
int STSize(ST* pst)
{
	assert(pst);

	return pst->top;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值