用俩个栈模拟实现一个队列,如果栈的容量分别是O和P(O>P),那么模拟实现的队列最大容量是多少?

这篇博客探讨了如何使用两个有限容量的栈来模拟一个队列,并着重讨论了在栈的容量分别为O和P(O>P)时,模拟队列的最大容量问题。作者指出,最大容量为2P+1,这取决于数据在两个栈之间的转移策略。文章还提醒在设计有限容量栈的队列时需要注意栈的push操作。

刚才做题碰到了这个有意思的题。
两个栈实现队列是《剑指offer》上的题,大家之前或许都有做过。
这道题有意思在栈的容量是受限的,求的是容量。

这道题应该再深入的思考下,

首先,到底如何用两个栈实现队列。

大家都知道栈是FILO,队列是FIFO。可真正该实现的是时候就不是简简单单的想 着把一个栈里的数据,存入另一个栈中,这样再取出来就是先进的先出了。
关键问题是何时将一个栈中的数据存入另一个栈
栈和队列的关键操作是push()pop(),前者负责压入一个数据,后者负责弹出。还有个top()/front()分别取栈顶/队首元素。那应该如何用俩栈实现队列的push()呢?

class DemoQueue
{
	stack<int> s1, s2;
public:
	void push(int val)
	{
	//	s2.push(val);  直接存入第二个栈等着pop()? 连着存多个push()不就跟stack一样了么,显然不行。
		s1.push(val); 
	// s2.push(val)   每push一次都要更新s2以使pop()能正常pop()? 显然也不行,要知道pop()的关键是要保证s2的top()时刻都是队列的队首 
	}
	//所以其实push只需压入数据给第一个栈就好了。
	void pop()
	{
		//那pop()就需要下功夫,要知道客户有可能在任何时候调用pop()
		if (s1.empty() && s2.empty())
			throw "Wtf";
		//首先,如果s2没有任何数据,那就得从s1调,并且是全调,因为s1的栈底存的是最早进入的数据。
		if (s2.empty())
		{
			while (!s1.empty())
			{
				s2.push(s1.top());
				s1.pop();
			}
		}
		//这时s2栈顶就是队首,我们再想如果s2里本来就有数据呢?那么这个数据其实就是队首!不需要从s1调。
		//也就是说,s2直接pop()就行了。
		s2.pop();
	}
};

其实大家都懂,我真不该费笔墨墨迹这半天。

然后关键是这题它限制了栈是有容量的,而且是求队列的最大容量,我寻思半天选个O+P(亏我还之前实现过,换个思路就懵逼了)。

为什么要选O+P,我以为队列最大的容量就存呗,O存满了再存P,那就是最大了呗。

其实还是这栈与队列的转换原理不够透彻。要知道一个栈存满了是要把这个栈的所有元素转移到另一个栈,再存这个栈的,并且要保证等全push()完后pop()的对,是FIFO

那么有两种存储方式:

1)如果先存容量为P的栈(以下简称P),P存满了把P的数据全压入O,因为O比P大,O是未满的,但是没有办法把它填满了,因为O目前的栈顶就是队首。 所以最大存储量就是2P。
2)如果先存O, 不能直接存满O,因为P<O,存满O,再转入P,P的栈顶不是队首。那就还是存个P,但最大不是2P,因为O第一次存P个数据转入P后,O可以存个P+1个,对你想的没错,O最后剩的那个是队列pop()P次后的队首。

总结:最大存 2P+1

延展思维:

既然栈可能有容量,那么要是用有容量的栈设计队列需要注意哪里呢?
我认为改个push就好啦

stack<int> s1, s2;
int s2MAX_SIZE;//s1比s2容量大
public:
	void push(int val)
	{
		if (s1.size() + s2.size() == 2*s2MAX_SIZE)
		{
			cout << "No push, queue is full";
			return;
		}
		if (s1.size() == s2MAX_SIZE)
		{
			if (!s2.empty())
			{
				cout << "No push, queue is full";
				return;
			}
			while (!s1.empty())
			{
				s2.push(s1.top());
				s1.pop();
			}
		}
		s1.push(val);
	}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值