栈和队列的经典面试题(一)

一、 实现一个栈,要求实现Push(入栈)、Pop(出栈)、Min(返回最小值的操作)的时间复杂度为O(1)。  

分析:
    思路1 :利用两个栈,第二个栈的栈顶只放当前原生栈的最小值,Pop和Push时两个栈都进行,Min时只有第二个栈返回其栈顶值。
    eg1—— 以入栈 5 3 6 7 8 0 为例,其入栈、求最小值、出栈的过程如下图:

此思路在本例题下可行,但如果换个例子,要求入栈 5 3 6 3 3 0 的话就会出状况,这个时候,需要进行改进。
     改进1 :如果原生栈中的元素不重复时,第二个栈中不出现重复数字;若原生栈中的元素出现重复时,第二个栈中同样引入该重复数字。 Push时第二个栈只压入截至目前的最小值和原生栈中重复的数,Pop时第二个栈只在等于原生栈中值时才出,Min时只有第二个栈返回其栈顶值。 入栈、求最小值、出栈的过程如下图:

但这时仍然存在问题,即当原生栈需要压入的数据有大量重复的时候,思路二的方法的效率就会显得很低。这时仍需要进行改进。
    改进2 :使用引用计数,对第二个栈中的每个数配一个引用计数,当引用计数为0时再Pop。此方法为最优方法。
实现:
思路1实现:
#include <iostream>
#include <stack>
using namespace std;
template <class T>
class MinStack
{
public:
       void Push(const T& x)
       {
              _st.push(x);
              if ((_minst.empty()) || (x < _minst.top()))
              {
                     _minst.push(x);     //minst为空时直接压栈,不为空时需要判断是否为当前最小值
              }
              else
              {
                     _minst.push(_minst.top());  //保持压入最小值
              }
       }
       void Pop()
       {
              _st.pop();
              _minst.pop();
       }
       void Min()
       {
              /*return _minst.top();*/
              cout << "min= " << _minst.top() << endl;
       }
       void Print()
       {
                     while (!_st.empty())
                     {
                           cout << _st.top() << " ";
                           _st.pop();
                     }
                     cout << endl;
       }
protected:
       stack<T> _st;
       stack<T> _minst;
};
int main()
{
       MinStack<int> s;
       s.Push(3);
       s.Push(2);
       s.Push(6);
       s.Push(5);
       s.Push(1);
       s.Push(7);
       /*s.Min();
       s.Print();*/
       s.Pop();
       s.Pop();
       s.Min();
       s.Print();
       system("pause");
       return 0;
}
改进1实现(只需更改Push和Pop):
void Push(const T& x)
       {
              _st.push(x);
              if ((_minst.empty()) || (x <= _minst.top()))
              {
                     _minst.push(x);     //minst为空时直接压栈,不为空时需要判断是否为最小值或重复值
              }
       }
       void Pop()
       {
              if (_st.top() == _minst.top())
              {
                     _minst.pop();
              }
              _st.pop();
       }     
改进2的实现:
template <class T>
class MinStack
{
public:
       struct ValueRef    //定义一个内部类作第二个栈
       {
              T _value;
              size_t _ref;    //计数
              ValueRef()   //构造 初始化_ref
                     :_ref(0)
              {}
       };
protected:
       stack<T> _st;
       stack<ValueRef> _minst;
};
添加内部类,其他运算据此进行。

二、使用两个栈实现一个队列。

分析:
有两个栈s1和s2,s1负责入队,压栈即可。出队时,若s2为空,将s1中元素导入s2中,若s2不为空,由s2出栈来完成出队。

实现:
#include <iostream>
#include <stack>
using namespace std;
template <typename T>
class CQueue
{
public:
       CQueue(void)
       {}
       ~CQueue(void)
       {}
       void appendTail(const T& node);
       T deleteHead();
private:
       stack<T> stack1;
       stack<T> stack2;
};
template<class T>
void CQueue<T>::appendTail(const T& node)//在队列尾部添加数据
{
       stack1.push(node);
}
template<class T>
T CQueue<T>::deleteHead()
{
       T tmp = 0;
       if (stack2.empty()) //若栈2为空
       {
              while (!stack1.empty())
              {
                     tmp = stack1.top();
                     stack2.push(tmp);
                     stack1.pop();
              }
       }
       tmp = stack2.top();
       stack2.pop();
       return tmp;
}
void Test()
{
       CQueue<int> q1;
       q1.appendTail(1);
       q1.appendTail(2);
       q1.appendTail(3);
       q1.appendTail(4);
       q1.deleteHead();
       q1.appendTail(5);
       q1.appendTail(6);
       q1.appendTail(7);
}
int main()
{
       Test();
       system("pause");
       return 0;
} 

三、 使用两个队列实现一个栈

分析:
进栈:把元素push进非空的队列,如果两者都是空的,则随意。  
出栈:把非空队列里面的前n-1个元素push到空队列里面,再把最后一个元素拿出来即可。  
循环以上步骤,即可得到实现目的。
实现:
#include "queue"
#include "iostream"
using namespace std;
template <typename T>
class Stack {
public:
       Stack() {
              count = 0;
       }
       ~Stack() {}
       void push(const T & data) {
              if (!q2.empty()) {
                     q2.push(data);
              }
              else {
                     q1.push(data);
              }
              count++;
       }
       T pop() {
              T temp;
              if (!q1.empty()) {
                     for (int i = 0; i < count - 1; ++i) {
                           q2.push(q1.front());
                           q1.pop();
                     }
                     temp = q1.front();
                     q1.pop();
                     count--;
                     return temp;
              }
              else if (!q2.empty()) {
                     for (int i = 0; i < count - 1; ++i) {
                           q1.push(q2.front());
                           q2.pop();
                     }
                     temp = q2.front();
                     q2.pop();
                     count--;
                     return temp;
              }
       }
       T top() {
              T temp;
              if (!q1.empty()) {
                     for (int i = 0; i < count - 1; ++i) {
                           q2.push(q1.front());
                           q1.pop();
                     }
                     temp = q1.front();
                     q2.push(temp);
                     q1.pop();
                     return temp;
              }
              else if (!q2.empty()) {
                     for (int i = 0; i < count - 1; ++i) {
                           q1.push(q2.front());
                           q2.pop();
                     }
                     temp = q2.front();
                     q1.push(temp);
                     q2.pop();
                     return temp;
              }
       }
       int size() const { return count; }
       bool empty() {
              return count == 0;
       }
private:
       queue<T> q1;
       queue<T> q2;
       int count;
};
template <typename T>           //注意非模板类的成员函数的模板姿势
int print(Stack<T> s) {
       while (!s.empty()) {
              cout << s.pop() << " ";
       }
       cout << endl;
}



猜你喜欢

转载自blog.csdn.net/gunqu_d/article/details/78835976
今日推荐