两个队列模拟一个栈
上文给出了两个栈模拟一个队列的解法,本文继续解决两个队列模拟一个栈的问题。
先进先出变成先进后出,乍一想可能觉得不可能。但是这道题的前提是用两个队列,我们完全可以用其中一个队列queue1保存好要出栈的元素,每当有新元素要入栈的时候就把他加到queue1中。怎么让queue1中的元素按出栈顺序排列呢,即怎么把进入到队列中的元素反转过来呢?这时候queue2派上了用场。
思路1:
利用一个指针指向其中一个空队列,这个空队列用来入栈;另外需要一指针指向另一个队列,用于出栈。有新元素要入栈时的操作:将新元素加入到空队列中,若另一个队列不为空,则把另一个队列中的元素转移到刚刚入栈的空队列中,最后交换两个指针的指向;出栈时的操作很简单,直接根据出栈队列的指针找到出栈队列,从队列中取出第一个元素即为出栈,别忽略了边界情况判断。
比如,12345入栈的过程如下图所示:
如果把队列比喻成两两根管子,元素比喻成小球。则上面的思路总结起来就是:总是把新的小球放到空管里,它自然会下沉到管子的最下面,然后把另一根管子里的小球顺到这个管子里来。需要拿出小球的时候,就找到有小球的管子,把最下面的小球放出来。
思路2:
用一个指针指向一个队列用于出栈和入栈。入栈时直接将元素加入到队列中;出栈时,把队列中除最后加入的元素外全部转移到另一个队列中。这样最后加入的元素自然可以出栈。以12345入栈再顺序出栈为例,下图中表格1为入栈后的状态。面的表格分别为2345出栈过程,元素转移后出栈前的状态
上面两种思路的不同点在于翻转元素顺序的操作在入栈时还是在出栈时。但是,都有一个局限,栈的容量等于其中容量最小的队列的容量。相较于栈,队列的出队入队操作分别在两端,这里可以利用这个特点进行优化。
思路3:
模拟一个栈非得用两个队列吗?栈中的元素出栈后,再入栈的话,还是在原来的位置;队列中的元素则可以出队再入队实现从队列头部到队列尾部的转移,而且把队列看成一个循环的序列的话,它还是有序的,只要我们还能找得到它的头和尾。对于两个队列,仍然可以首尾相接形成一个环。我们只需要遵循下面两个原则即可,出栈时旋转序列,使得要出栈的元素位于队列的头部,然后从队列中取出;入栈时旋转序列,使得序列的尾部正好出现在队列的尾部,并且有空间可以加入新元素,然后新元素加入队列。以1234567入栈,然后7出栈为例,下图第一个表为12345入栈后的状态,第二个和第三个表分别为6、7入栈后的状态,最后一个表为7出栈前的状态。