剑指Offer精选编程面试题9-用两个栈实现队列(相关题目:用两个队列实现栈)

本文介绍了如何使用两个栈实现一个队列,以及如何使用两个队列实现一个栈。详细阐述了Push和Pop操作的实现思路,并讨论了优化方法,包括避免不必要的元素转移。同时,给出了实现这两种数据结构转换的关键代码片段。
摘要由CSDN通过智能技术生成

1)题目

用两个栈实现队列(相关题目:用两个队列实现栈)

要求:
  • 用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
  • 用两个队列来实现一个栈,完成栈的Push和Pop操作。栈中的元素为int类型。

2)思路

首先需要明确栈和队列的特点,栈为“先进后出”结构,队列为”先进先出“结构。

(1)用两个栈来实现一个队列的思路

  • 实现队列的push操作: 首先创建两个栈stack1与stack2,将元素压入stack1,此时stack2为空。
  • 实现队列的pop操作: 由于队列为”先进先出“结构,所以先压入stack1的元素需要先出列,分两种情况,第一,在stack2为空的和stack1不为空的情况下,将stack1的元素出栈并一一压入stack2中,就把原来在stack1栈底的元素现在在stack2的栈顶,所以直接pop出stack2的栈顶元素即可完成队列的pop操作。第二种情况为stack2不为空,那直接pop出stack2的栈顶元素即可完成队列的pop操作。

存在问题:

上述思路,可行性毋庸置疑。但有一个细节是可以优化一下的。即:在出队时,将s1的元素逐个“倒入”s2时,原在s1栈底的元素,不用“倒入”s2(即只“倒”s1.Count()-1个),可直接弹出作为出队元素返回。这样可以减少一次压栈的操作

三个方法变种:

  • 入队时,先判断s1是否为空,如不为空,说明所有元素都在s1,此时将入队元素直接压入s1;如为空,要将s2的元素逐个“倒回”s1,再压入入队元素。
  • 出队时,先判断s2是否为空,如不为空,直接弹出s2的顶元素并出队;如为空,将s1的元素逐个“倒入”s2,把最后一个元素弹出并出队。
  • 入队时,将元素压入s1。出队时,判断s2是否为空,如不为空,则直接弹出顶元素;如为空,则将s1的元素逐个“倒入”s2,把最后一个元素弹出并出队。这个思路,避免了反复“倒”栈,仅在需要时才“倒”一次。

上述方法总体上时间复杂度和空间复杂度应该相差无几。
注意事项:

要考虑没有元素可供出队时的处理(2个栈都为空的时候,出队操作一定会引起异常)。在实际写代码时,忽略这些判断或异常处理,程序会出现问题
在这里插入图片描述
(2)用两个队列来实现一个栈的思路

  • 实现栈的push操作: 新元素入栈时,若两个队列都为空,向任意一个队列队尾插入元素,否则向其中一个非空队列插入元素。
  • 实现栈的pop操作: 由于队列为”先进后出“结构,所以先入队的元素需要先出栈,栈弹出元素时,将非空队列的元素依次删除,插入另一个空队列,只留下队尾元素(此即栈顶元素),弹出栈顶即从队列中删除此元素。

注意事项:
在此过程中,新push进来的元素总是插入到非空队列中,空队列则用来保存pop操作之后的那些元素,那么此时空队列不为空了,原来的非空队列变为空了,总是这样循环。

3)代码

参考文章1
参考文章2
代码分为两部分,用两个栈来实现一个队列,完成队列的Push和Pop操作。用两个队列来实现一个栈,完成栈的Push和Pop操作。栈中的元素为int类型。

(1)用两个栈来实现一个队列,完成队列的Push和Pop操作

//第三种方案
#pragma once
#include <iostream>
#include<vector>
#include <stack>
using namespace std;
class CQeue
{
private:
	stack<int> stack1;
	stack<int> stack2;

public:
	void appendtail(int element)
	{
		stack1.push(element);
	}

	int deletehead()
	{
		if (stack2.size() <= 0)
		{
			while (stack1.size() > 0)
			{
				int data=stack1.top();
				stack1.pop();
				stack2.push(data);
				
			}
		}

		if (stack2.size() == 0)
		{
			cout << "stack is empty" << endl;
		}
		int head=stack2.top();
		stack2.pop();
		return head;
	}
};

主函数
//#include <iostream>
//#include "offer_9.h"
//using namespace std;
//
//
//int main()
//{
//	CQeue temp;
//	//temp.appendtail(1);
//	//temp.appendtail(2);
//	//temp.appendtail(3);
//	int result = temp.deletehead();
//	//cout << result << endl;
//	//int result1 = temp.deletehead();
//	//cout << result1 << endl;
//	//int result2 = temp.deletehead();
//	//cout << result2 << endl;
//	return 0;
//}

(2)用两个队列来实现一个栈,完成栈的Push和Pop操作

要点:新元素入栈时,若两个队列都为空,向任意一个队列队尾插入元素,否则向其中一个非空队列插入元素。栈弹出元素时,将非空队列的元素依次删除,插入另一个空队列,只留下队尾元素(此即栈顶元素),弹出栈顶即从队列中删除此元素。

#pragma once
#include <iostream>
#include <stack>
#include <queue>
using namespace std;

class CStack
{
private:
	queue<int> queue1;
	queue<int> queue2;

public:
	void appendtail(int element)
	{
		if (queue1.empty())
		{
			queue2.push(element);
		}
		else if (queue2.empty())
		{
			queue1.push(element);
		}
	}
	int deletehead()
	{
		int head;
		if (queue2.empty())
		{
			while (queue1.size() != 1)
			{
				int data = queue1.front();
				queue2.push(data);
				queue1.pop();
			}
			head = queue1.back();
			queue1.pop();
		}
		else if (queue1.empty())
		{
			while (queue2.size() != 1)
			{
				int data = queue2.front();
				queue1.push(data);
				queue2.pop();
			}
			head = queue2.back();
			queue2.pop();
		}


		return head;
	}
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值