堆 队列
A Stack is a Last In First Out(LIFO) structure, i.e, the element that is added last in the stack is taken out first. Our goal is to implement a Stack using Queue for which will be using two queues and design them in such a way that pop operation is same as dequeue but the push operation will be a little complex and more expensive too.
堆栈是后进先出(LIFO)结构,即, 首先取出在堆栈中最后添加的元素。 我们的目标是实现一个使用队列的堆栈,该堆栈将使用两个队列,并以弹出操作与出队相同的方式设计它们,但推送操作将稍微复杂一些,并且也更加昂贵。
使用队列实现堆栈 (Implementation of Stack using Queue)
Assuming we already have a class implemented for Queue, we first design the class for Stack. It will have the methods push()
and pop()
and two queues.
假设我们已经为Queue实现了一个类,我们首先为Stack设计该类。 它将具有方法push()
和pop()
以及两个队列。
class Stack
{
public:
// two queue
Queue Q1, Q2;
// push method to add data element
void push(int);
// pop method to remove data element
void pop();
};
将数据插入堆栈 (Inserting Data in Stack)
Since we are using Queue which is First In First Out(FIFO) structure , i.e, the element which is added first is taken out first, so we will implement the push operation in such a way that whenever there is a pop operation, the stack always pops out the last element added.
由于我们使用的是先进先出(FIFO)结构的队列,即首先取出的是最先添加的元素,因此我们将以这样的方式实现推送操作:只要有弹出操作,堆栈总是弹出最后添加的元素。
In order to do so, we will require two queues, Q1
and Q2
. Whenever the push operation is invoked, we will enqueue(move in this case) all the elements of Q1
to Q2
and then enqueue the new element to Q1
. After this we will enqueue(move in this case) all the elements from Q2
back to Q1
.
为此,我们将需要两个队列Q1
和Q2
。 每当调用push操作时,我们都会将Q1
所有元素排队(在这种情况下移动)到Q2
,然后将新元素排队到Q1
。 之后,我们将把所有元素从Q2
队(在这种情况下移动)回到Q1
。
So let's implement this in our code,
因此,让我们在代码中实现它,
void Stack :: push(int x)
{
// move all elements in Q1 to Q2
while(!Q1.isEmpty())
{
int temp = Q1.deque();
Q2.enque(temp);
}
// add the element which is pushed into Stack
Q1.enque(x);
// move back all elements back to Q1 from Q2
while(!Q2.isEmpty())
{
int temp = Q2.deque();
Q1.enque(temp);
}
}
It must be clear to you now, why we are using two queues. Actually the queue Q2
is just for the purpose of keeping the data temporarily while operations are executed.
现在您必须清楚知道为什么我们要使用两个队列。 实际上,队列Q2
仅用于在执行操作时临时保留数据的目的。
In this way we can ensure that whenever the pop operation is invoked, the stack always pops out the last element added in Q1
queue.
这样,我们可以确保每当调用pop操作时,堆栈始终弹出在Q1
队列中添加的最后一个元素。
从堆栈中删除数据 (Removing Data from Stack)
Like we have discussed above, we just need to use the dequeue operation on our queue Q1
. This will give us the last element added in Stack.
就像我们上面讨论的一样,我们只需要在队列Q1
上使用出队操作。 这将为我们提供Stack中添加的最后一个元素。
int Stack :: pop()
{
return Q1.deque();
}
时间复杂度分析 (Time Complexity Analysis)
When we implement Stack using a Queue the push operation becomes expensive.
当我们使用队列实现Stack时, 推送操作变得很昂贵。
Push operation: O(n)
推动操作:O(n)
Pop operation: O(1)
弹出操作:O(1)
结论 (Conclusion)
When we say "implementing Stack using Queue", we mean how we can make a Queue behave like a Stack, after all they are all logical entities. So for any data structure to act as a Stack, it should have push()
method to add data on top and pop()
method to remove data from top. Which is exactly what we did and hence accomplished to make a Queue(in this case two Queues) behave as a Stack.
当我们说“使用队列实现堆栈”时,是指我们如何使队列的行为像堆栈一样,毕竟它们都是逻辑实体。 因此,对于要用作堆栈的任何数据结构,它都应具有push()
方法在顶部添加数据,而pop()
方法从顶部删除数据。 这正是我们所做的,因此完成了使一个Queue(在本例中为两个Queue)表现为堆栈的工作。
翻译自: https://www.studytonight.com/data-structures/stack-using-queue
堆 队列