高频面试题*两个栈实现一个队列:
谈到栈实现队列首先我们必须了解栈和队列的特点:
栈:只允许在栈顶插入和删除。
队列:插入在对尾操作,删除在对头操作.
两个栈实现一个队列:
(ps:这道题对编程者或面试者的要求:
1. 在短时间内,能不能找到解决这道题的足够清晰的思路(思维是否敏捷、清晰)。
2. 能不能在单向表述中,清楚地描述自己的思路和想法(表述能力是否达到要求)。
3. 对于某些具体细节,能不能考虑到(是否足够细致)。
方法一:入队时直接把元素push到s1,出队时把s1倒入s2,pop掉s2栈顶元素,再倒回到s1.
代码实现:
(ps:这里出队时当s1,s2都为空的时候采用了抛出异常的方法,方法二和方法三都是首先用if做出了判断)
<span style="font-family:SimSun;font-size:18px;">#include<iostream>
using namespace std;
#include<stack>
template<typename T>
class Queue
{
public:
void push(const T& x)
{
s1.push(x);
}
void pop()
{
if (s1.empty() && s2.empty())
{
cout << The Queue is empty; << endl;
}
while (s1.empty())
{
s2.push(s.top());
s1.pop()
}
s2.pop();
while (s2.empty())
{
s1.push(s2.top());
s2.pop()
}</span>
<span style="font-family:SimSun;font-size:18px;"> void Print1()
{
if (s1.empty())
{
cout << "The Queue is empty" << endl;
return;
}
cout << "Queue: ";
while (!s1.empty())
{
cout << s1.top() << " ";
s1.pop();
}
cout << endl;
}
}
private:
stack<T>s1;
stack<T>s2;
};</span>
方法二:入队:s1不为空时,直接把元素压入s1,s1为空时,把s2倒入s1,再把元素压入s1.
出队:s2不为空时,直接弹出s2栈顶的元素,s2为空时,先把s1倒入s2,再弹出s2栈顶的元素。
代码实现:
template <typename T>
class Queue
{
public:
void push(const T&x)
{
if (!s1.empty())
{
s1.push(x);
}
else
{
while (!s2.empty())
{
s1.push(s2.top());
s2.pop();
}
s1.push(x);
}
}
void pop()
{
if (!s2.empty())
{
s2.pop();
}
else if (s2.empty())
{
while (!s1.empty())
{
s2.push(s1.top());
s1.pop();
}
s2.pop();
}
else if (s1.empty() && s2.empty())
{
int value = 0;
try
{
throw value;
}
catch (int)
{
cerr << "The stack is empty,can't pop the data" << endl;
//exit(1);
}
}
}
void Print1()
{
if (s1.empty())
{
cout << "The Queue is empty" << endl;
return;
}
cout << "Queue: ";
while (!s1.empty())
{
cout << s1.top() << " ";
s1.pop();
}
cout << endl;
}
private:
stack<T> s1;
stack<T> s2;
};
方法三:入队时直接把元素压入s1;
出队时如果s2不为空,直接弹出s2栈顶元素,如果s2为空,把s1倒入s2,再弹出s2栈顶元素。
图解:
代码实现:
<span style="font-family:SimSun;font-size:18px;">template<typename T>
class Queue
{
public:
void push(const T& x)
{
s1.push(x);
}
void pop()
{
if (s1.empty() && s2.empty())
{
cout << "The Queue is empty"<<endl;
return;
}
if (!s2.empty())
s2.pop();
while (!s1.empty())
{
s2.push(s1.top());
s1.pop();
}
s2.pop();
}
void Print3()
{
if (s1.empty())
{
cout << "The Queue is empty;" << endl;
return;
}
cout << "s1.Queue:";
while (!s1.empty())
{
cout << s1.top() << " ";
s1.pop();
}
cout << endl;
}
private:
stack<T> s1;
stack<T> s2;
};</span>
测试用例:
<span style="font-family:SimSun;font-size:18px;">void QueueTest1()
{
Queue<int> s1;
s1.push(1);
s1.push(2);
s1.push(3);
s1.push(4);
s1.push(5);
s1.push(6);
s1.Print3();
}
//void QueueTest2()
//{
// Queue<int> s2;
// s2.pop();
// s2.pop();
// s2.pop();
// s2.pop();
// s2.Print3();
//}</span>
主函数:
<span style="font-size:18px;">int main()
{
QueueTest1();
QueueTest2();
system("pause");
return 0;
}</span>
总结:栈和队列各有自己的特点,栈适合用数组结构即顺序表结构实现,而队列适合用链表结构实现,就栈和队列本身而言不但可以相互实现,而且在数据结构中有举足轻重的作用,二叉树的遍历就要用到栈和队列。本文调用的都是系统的栈,栈的实现就不多在这描述了。值得注意的是栈和队列各自的特点以及栈和队列不同操作所在的位置。文章前面都已悉数提到。