栈与队列的应用

       在“栈与队列的应用(上)”中,通过讨论两个队列实现一个栈和两个栈实现一个队列这两个问题,我们对栈和队列也有了更深的了解,下面我们主要来讨论以下两个面试中常常会遇到的问题:

1)一个数组实现两个栈

2)实现一个栈,能够push、pop、min(求栈中最小的数据)


问题一:

      对于一个数组,我们如何能够使其成为两个栈?根据数组和栈的特点,我们不难发现可以将数组的两端作为栈的栈底,使用两个指针分别指向数组的开始位置和末尾位置,假设将数组的左边作为栈s1,数组的右边作为栈s2,若s1中的栈顶指针向后在偏移一个位置与另一个指针同时指向一块空间,此时就称为“栈满”,不能进行插入操作。如果想要对栈进行操作,就必须要指定对哪个栈操作。这里使用了两个整形变量用来记录栈s1和栈s2的栈顶的位置下标,对其进行操作。


下面为简单的图示:

wKiom1cUyGeDapT8AAAOQWIGo3o224.png


下面是具体的程序代码:


//一个数组实现两个栈
//方法一:(静态数组)
#include <iostream>
using namespace std;
#include <stdlib.h>
#define MAX 100

template <class T>
class TwoStack
{
public:
     TwoStack()     //构造函数
          :_array(new T[MAX])
          , lefttop0(-1)
          , righttop1(MAX)
     { }

public:
     void Push(T x, int i)     //压栈,将数据压入i号栈中
     {
          if (lefttop0 + 1 == righttop1)
          {
               cout << "栈已满,不能压栈!";
               return;
          }
          else
          {
               switch (i)
               {
                   case 0:                       //压入0号栈中
                        lefttop0++;
                        _array[lefttop0] = x;
                        break;
                   case 1:               //压入1号栈中
                        righttop1--;
                        _array[righttop1] = x;
                        break;
                   default:
                        break;
               }
          }
     }
     
     void Pop(int i)     //i号栈、元素出栈
     {
          switch (i)
          {
              case 0:
                   if (lefttop0 == -1)
                   {
                        cout << "The Stack is Empty!" << endl;
                   }
                   lefttop0--;
                   break;
              case 1:
                   if (righttop1 == MAX)
                   {
                        cout << "The Stack is Empty!" << endl;
                   }
                   righttop1++;
                   break;
              default:
                   break;
          }
     }
     
     T& top(int i)          //读取i号栈中元素
     {
          if (i == 0)
          {
               return _array[lefttop0];
          }
          else
          {
               return _array[righttop1];
          }
     }
     
     void Display(int i)      //打印i号栈的元素
     {
          if (i == 0)
          {
               cout << "打印0号栈中的元素:" << endl;
               while (lefttop0 != -1)
               {
                    cout << _array[lefttop0] << " ";
                    lefttop0--;
               }
               cout << endl;
          }
          else if (i == 1)
          {
               cout << "打印1号栈中的元素:" << endl;
               while (righttop1 != MAX)
               {
                    cout << _array[righttop1] << " ";
                    righttop1++;
               }
               cout << endl;
          }
     }
     
private:
     T* _array;
     int lefttop0;
     int righttop1;
};


问题二:

       这个问题主要是要实现求栈中最小数据,完成这个功能,就需要借助另一个栈对最小数据进行保存,假设现有栈s1和栈s2,当向s1中插入第一个数据时,同时也向s2中插入相同的数据,下来在向s1中插入第二个数据,此时若第二个数据小于s2的栈顶数据,此时也将与之相同的数据插入s2中,若第二个数据小于s2的栈顶数据,则不用向s2中插入数据,按照这样的方式插入数据。现在就能够显而易见的知道s2中的栈顶数据就是栈s1中的最小数据。

       如果需要对s1中数据进行删除,如若s1中要删除的数据与s2中要删除的数据相同,则栈s2中同样删除栈顶元素,若不等,则将s1中栈顶元素删除就行,不需要删除s2中的数据。这样就能够始终保持s2中栈顶数据为栈s1中的最小数据。


下面是简单的图示:

wKiom1cUza2hBQvPAAAWHmLQRYg900.png

下面为具体的程序代码:


//判断出对序列中的最小数据
//实现一个栈,要求实现Push、pop、min(返回栈中最小值)的时间复杂度为o(1)。
#include <iostream>
using namespace std;
#include <stdlib.h>
#include <stack>

template <class T>
class Stack
{
public:
     void Push(const T& x)
     {
          if (s1.empty() && s2.empty())
          {
               s1.push(x);
               s2.push(x);
          }
          else if (!s1.empty())
          {
               if (x < s2.top())
               {
                    s1.push(x);
                    s2.push(x);
               }
               else
               {
                    s1.push(x);
               }
          }
     }
     
     void Pop()
     {
          if (!s1.empty() && !s2.empty())
          {
               if (s1.top() == s2.top())
               {
                    s1.pop();
                    s2.pop();
               }
               else
               {
                    s1.pop();
               }
          }
     }
     
     T minNumber()
     {
          return s2.top();
     }
private:
     stack<T> s1;
     stack<T> s2;
};