经典面试题之-用两个队列实现一个栈(超详细! 简单易懂!)

本文详细介绍了如何使用C++中的两个队列来模拟栈的push、pop、top和empty操作,通过队列的先进先出和后进先出特性实现栈的功能,附有代码示例和LeetCode题目链接。
摘要由CSDN通过智能技术生成

本文章适用于了解过栈和队列结构的读者阅读,本文章代码使用c++实现!

目录

1.栈和队列的特点

1.1: 栈的特点

1.2: 队列的特点

2.如何使用两个队列来模拟栈的各种操作?

2.1分析结构

3.分析结束,代码实现

3.1整体框架

3.2函数Push

3.3函数Empty

3.4函数Pop

3.5函数Top

4.简单测试

5.整体代码

6.LeetCode该题链接

7.总结


1.栈和队列的特点

栈和队列都是比较常见的数据结构

1.1: 栈的特点

栈的特点就是后插入的数据先出来,所谓后进先出

一个经典的例子就是手枪中的子弹,最后压入的子弹最先打出来

1.2: 队列的特点

先插入的数据先出来,先进先出

一个经典的例子就是排队

2.如何使用两个队列来模拟栈的各种操作?

假如面试官现在给你提供了两个完备的队列,你可以使用队列中的各种操作,如pop,push,front等。

最后能够实现队列中的pop,push,front等操作

本文使用c++ stl中的queue作为面试官提供的队列。

2.1分析结构

假设我们在栈中插入数据1 2 3,然后在删除3,再插入数据 4 5,最后依次弹出

那么我们得到到弹出序列应该为 3 5 4 2 1

如果使用两个队列来实现,第一次插入数据时,在第一个队列中插入数据即可

每当要弹出数据的时候,我们要删除的栈顶元素为这个队列的队尾元素,如下图

然后弹出栈顶的3(即队列队尾的3)

那么,我们如何操作呢? 由于队列是先进先出,可以将先进去的1,2插入到队列2中,如下图

每次将有数据的队列中的数据除了队尾的元素以外,都插入到另一个队列中即可

这样我们直接队列1中删除队首元素即可(此时只有一个元素)

每次插入新的数据的时候,我们在不为空的队列中插入数据即可。

如下图

此时弹出所有数据,将1 2 4 插入到队列1中,再删除 队列2的5即可.如下图

之后依次删除即可得到正确的结果

3.分析结束,代码实现

3.1整体框架

//利用两个队列实现栈
class MyStack
{
public:
	MyStack()
	{
        queue<int> q1;
	    queue<int> q2;
    }
	//删除数据
	void Pop()
	{}

	//插入数据
	void Push(int x)
	{}

	//返回队列开头的数据
	int Top()
	{}

	//判断是否为空
	bool Empty()
	{}
private:
	queue<int> q1;
	queue<int> q2;
};

3.2函数Push

在不为空的队列中插入数据即可(第一次插入数据的时候随便哪个队列插入数据)

//插入数据
	void Push(int x)
	{
		if (q1.empty())
		{
			q2.push(x);
		}
		else//q1不为空
		{
			q1.push(x);
		}
	}

3.3函数Empty

用来判断栈是否为空,两队列都为空则栈为空

//判断是否为空
	bool Empty()
	{
		return q1.empty() && q2.empty();
	}

3.4函数Pop

将不为空的栈中数据除了队尾数据,都插入到另一个队列中。

然后删除这个队尾元素即可

	//删除数据
	void Pop()
	{
		//栈为空,不能够删除数据
		if (Empty())
		{
			cout << "栈中没有数据可以删除!";
			return;
		}

		if (!q1.empty())
		{
			//将不为空的队列中,除了队尾的数据都插入到另一个队列中
			while (!q1.empty())
			{
				if (q1.size() == 1)
					break;
				q2.push(q1.front());
				q1.pop();
			}
			//删除最后的数据
			q1.pop();
		}
		else
		{
			while (!q2.empty())
			{
				if (q2.size() == 1)
					break;
				q1.push(q2.front());
				q2.pop();
			}
			q2.pop();
		}
	}

3.5函数Top

返回栈顶元素,和pop类似,用一个变量t保留队尾元素即可

注意,在这个函数中,要将一个队列中所有的数据都插入到另外一个队列中

否则会删除元素,让栈出现错误删除

//返回队列开头的数据
	int Top()
	{
		//栈为空,无栈顶元素
		if (Empty())
		{
			cout << "栈中没有元素!";
			exit(-1);
		}

		int t = 0;
		if (!q1.empty())
		{
			//将不为空的队列中,除了队尾的数据都插入到另一个队列中
			while (!q1.empty())
			{
				if (q1.size() == 1)
					break;
				q2.push(q1.front());
				q1.pop();
			}
			//记录栈顶元素,注意要将所有的数据插入到另外一个队列中
			t = q1.front();
			q2.push(t);
			q1.pop();
		}
		else
		{
			while (!q2.empty())
			{
				if (q2.size() == 1)
					break;
				q1.push(q2.front());
				q2.pop();
			}
			t = q2.front();
			q1.push(t);
			q2.pop();
		}

		return t;
	}

4.简单测试

测试代码如下

void test_stack()
{
	MyStack s1;
	s1.Push(1);
	s1.Push(2);
	s1.Push(3);
	s1.Pop();
	s1.Push(4);
	s1.Push(5);
	while (!s1.Empty())
	{
		cout << s1.Top() << " ";
		s1.Pop();
	}
}


int main()
{
	test_stack();
	return 0;
}

正确的结果应该尾 5 4 2 1

运行结果如下

5.整体代码

#include<iostream>
#include<queue>
using namespace std;



//利用两个队列实现栈
class MyStack
{
public:
	MyStack()
	{
		queue<int> q1;
		queue<int> q2;
	}

	//删除数据
	void Pop()
	{
		//栈为空,不能够删除数据
		if (Empty())
		{
			cout << "栈中没有数据可以删除!";
			return;
		}

		if (!q1.empty())
		{
			//将不为空的队列中,除了队尾的数据都插入到另一个队列中
			while (!q1.empty())
			{
				if (q1.size() == 1)
					break;
				q2.push(q1.front());
				q1.pop();
			}
			//删除最后的数据
			q1.pop();
		}
		else
		{
			while (!q2.empty())
			{
				if (q2.size() == 1)
					break;
				q1.push(q2.front());
				q2.pop();
			}
			q2.pop();
		}
	}

	//插入数据
	void Push(int x)
	{
		if (q1.empty())
		{
			q2.push(x);
		}
		else//q1不为空
		{
			q1.push(x);
		}
	}

	//返回队列开头的数据
	int Top()
	{
		//栈为空,无栈顶元素
		if (Empty())
		{
			cout << "栈中没有元素!";
			exit(-1);
		}

		int t = 0;
		if (!q1.empty())
		{
			//将不为空的队列中,除了队尾的数据都插入到另一个队列中
			while (!q1.empty())
			{
				if (q1.size() == 1)
					break;
				q2.push(q1.front());
				q1.pop();
			}
			//记录栈顶元素,注意要将所有的数据插入到另外一个队列中
			t = q1.front();
			q2.push(t);
			q1.pop();
		}
		else
		{
			while (!q2.empty())
			{
				if (q2.size() == 1)
					break;
				q1.push(q2.front());
				q2.pop();
			}
			t = q2.front();
			q1.push(t);
			q2.pop();
		}

		return t;
	}

	//判断是否为空
	bool Empty()
	{
		return q1.empty() && q2.empty();
	}
private:
	queue<int> q1;
	queue<int> q2;
};


void test_stack()
{
	MyStack s1;
	s1.Push(1);
	s1.Push(2);
	s1.Push(3);
	s1.Pop();
	s1.Push(4);
	s1.Push(5);
	while (!s1.Empty())
	{
		cout << s1.Top() << " ";
		s1.Pop();
	}
}


int main()
{
	test_stack();
	return 0;
}

6.LeetCode该题链接

在力扣中有这道题,我们将代码输入到力扣中看一下是否能够通过力扣的测试

题目链接      225. 用队列实现栈 - 力扣(LeetCode)

该题中,top要返回删除的元素,简单修改即可(top函数类似)

直接通过

7.总结

使用队列来模拟栈,只要注意将一个队列中的数据除了队尾以外都插入另一个队列中就很简单

在写数据结构相关的题画图可以帮忙我们快速解决问题

⭐“我画了你身边每一个人,但却没有画你。我觉得你亮得耀眼,使我的目光无法停留。”

留个赞吧!

  • 13
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

橘子真甜~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值