高頻面試題*兩個棧實現一個隊列:
談到棧實現隊列首先我們必須瞭解棧和隊列的特點:
棧:只允許在棧頂插入和刪除。
隊列:插入在對尾操作,刪除在對頭操作.
兩個棧實現一個隊列:
(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>
總結:棧和隊列各有自己的特點,棧適合用數組結構即順序表結構實現,而隊列適合用鏈表結構實現,就棧和隊列本身而言不但可以相互實現,而且在數據結構中有舉足輕重的作用,二叉樹的遍歷就要用到棧和隊列。本文調用的都是系統的棧,棧的實現就不多在這描述了。值得注意的是棧和隊列各自的特點以及棧和隊列不同操作所在的位置。文章前面都已悉數提到。