/*****/栈和队列常见面试题

1.实现一个栈,要求实现Push(出栈)、Pop(入栈)、Min(返回最小值的操作)的时间复杂度为O(1)
因为栈的特点就是“先进后出,后进先出”,而且只能在栈顶进行操作,所以Push和Pop的时间复杂度就是O(1),要返回最小值的话,可以用一个数组(或栈)记录栈中前n项的最小值,以空间换时间,这样的话就能在O(1)内返回最小值了。
这里写图片描述

这里写图片描述

template<typename T>  
class Stack  
{  
public:  
       Stack()  
              :_ptr(NULL)  
              , _min(NULL)  
              , _size(0)  
              , _capacity(0){}  
       ~Stack()  
       {  
              delete[] _ptr;  
              delete[] _min;  
              _ptr = NULL;  
       }  
       void Push(const T& data);  
       void Pop();  
       T& Top();  
       bool Empty();  
       size_t Size();  
       T Min();  
       void CheckCapacity();  
protected:  
       T* _ptr;  
       T* _min;  
       int _size;  
       int _capacity;  
};  
template<typename T>  
T& Stack<T>::Top()  
{  
       assert(_size>=0);  
       return _ptr[_size - 1];  
}  
template<typename T>  
bool Stack<T>::Empty()  
{  
       if (_size == 0)  
              return true;  
       else  
              return false;  
}  
template<typename T>  
size_t Stack<T>::Size()  
{  
       return (size_t)_size;  
}  
template<typename T>  
void Stack<T>::Push(const T& data)  
{  
       CheckCapacity();  
       _ptr[_size] = data;  
       if (_size == 0)  
       {  
              _min[_size] = data;  
       }  
       else  
       {  
              if (data< _min[_size - 1])  
              {  
                     _min[_size] =data;  
              }  
              else  
              {  
                     _min[_size] =_min[_size-1];  
              }  
       }  
       _size += 1;  
}  
template<typename T>  
void Stack<T>::Pop()  
{  
       assert(_size >= 0);  
       --_size;  
}  
template<typename T>  
T Stack<T>::Min()  
{  
       assert(_size>=0);  
       return _min[_size-1];  
}  
template<typename T>  
void Stack<T>::CheckCapacity()  
{  
       if (_size >= _capacity)  
       {  
              int NewCapacity = _capacity * 2 + 3;  
              T* tmp1= new T[NewCapacity];  
              T* tmp2 = new T[NewCapacity];  
              for (int i = 0; i < _size; i++)  
              {  
                     tmp1[i] = _ptr[i];  
              }  
              delete[] _ptr;  
              _ptr = tmp1;  
              for (int i = 0; i < _size; i++)  
              {  
                     tmp2[i] = _min[i];  
              }  
              delete[] _min;  
              _min = tmp2;  
              _capacity = NewCapacity;  
       }  
}  

2.使用两个栈实现一个队列
因为栈是后进先出,而队列是先进先出,所以我们在用两个栈实现一个队列的时候,就要用两个栈来回交换,是它能够满座先进先出的特点。
这里写图片描述

#pragma once

    #include<iostream>
    #include<cstdlib>
    #include<cassert>
    #include<stack>
    using namespace std;

    template<typename T>
    class Queue
    {
    public:
        void push(const T& d);
        void pop();
        size_t size();
        bool empty();
        T& front();
        T& back();



    private:
        stack<T > s1;
        stack<T > s2;
    };

    template<typename T>
    void Queue<T>::push(const T& d)
    {
        s1.push(d);
    }
    template<typename T>
    void Queue<T>::pop()
    {
        assert((!s1.empty() )||(! s2.empty()));
        if (s2.empty())
        {
            while (!s1.empty())
            {
                s2.push(s1.top());
                s1.pop();
            }
        }
        s2.pop();
    }
    template<typename T>
    size_t Queue<T>::size()
    {
        return s1.size() + s2.size();
    }
    template<typename T>
    bool Queue<T>::empty()
    {
        return s1.empty()&&s2.empty();
    }
    template<typename T>
    T& Queue<T>::front()
    {
        assert((!s1.empty()) || (!s2.empty()));

        if (s2.empty())
        {
            while (!s1.empty())
            {
                s2.push(s1.top());
                s1.pop();
            }
        }
        return s2.top();
    }
    template<typename T>
    T& Queue<T>::back()
    {
        assert((!s1.empty()) || (!s2.empty()));

        if (s1.empty())
        {
            while (!s2.empty())
            {
                s1.push(s2.top());
                s2.pop();
            }
        }
        return s1.top();
    }

这里写图片描述

template<typename T>  
class Queue  
{  
public:  
       void Push(const T& data);  
       void Pop();  
       size_t Size();  
       bool Empty();  
       T& Front();  
       T& Back();  
private:  
       stack<T> _s1;           //_s1作为入队  
       stack<T> _s2;           //_s2作为出队  
};  
template<typename T>  
void Queue<T>::Push(const T& data)  
{  
       _s1.push(data);  
}  
template<typename T>  
void Queue<T>::Pop()  
{  
       assert((_s1.size()+_s2.size()));           //两个栈都为空,则队列已空  
       if (_s2.empty())                           //如果_s2以空,则需要把_s1中的元素导入_s2中  
       {  
              while (!_s1.empty())  
              {  
                     _s2.push(_s1.top());  
                     _s1.pop();  
              }  
       }  
       _s2.pop();  
}  
template<typename T>  
size_t Queue<T>::Size()  
{  
       return (_s1.size() + _s2.size());        //返回两个栈的元素之和  
}  
template<typename T>  
bool Queue<T>::Empty()  
{  
       if (_s1.empty() && _s2.empty())      //如果两个栈都为空,则返回true  
       {  
              return true;  
       }  
       else  
       {  
              return false;  
       }  
}  
template<typename T>  
T& Queue<T>::Front()  
{  
       assert((_s1.size() + _s2.size()));           //两个栈都为空,则队列已空  
       if (_s2.empty())                           //如果_s2以空,则需要把_s1中的元素导入_s2中  
       {  
              while (!_s1.empty())  
              {  
                     _s2.push(_s1.top());  
                     _s1.pop();  
              }  
       }  
       return _s2.top();  
}  
template<typename T>  
T& Queue<T>::Back()  
{  
       assert((_s1.size() + _s2.size()));           //两个栈都为空,则队列已空  
       if (_s1.empty())                    //_s1为空,则要把_s2栈中元素导入_s1  
       {  
              while (!_s2.empty())  
              {  
                     _s1.push(_s2.top());  
                     _s2.pop();  
              }  
       }  
       return _s1.top();  
}  

3.使用两个队列实现一个栈
这里写图片描述

#pragma once

#include<iostream>
#include<cstdlib>
#include<cassert>
#include<queue>

using namespace std;

template<typename T>
class Stack
{
public:
    void push(const T & d);
    void pop();
    size_t size();
    bool empty();
    T& top();
private:
    queue<T> q1;
    queue<T> q2;
};

template<typename T>
void Stack<T>::push(const T& d)
{
    if (q2.empty()&&q2.empty())
    {
        q1.push(d);
    }
    else if (!q1.empty())
    {
        q2.push(d);
    }
    else
        q1.push(d);

}
template <typename T>
void Stack<T>::pop()
{
    assert(!q1.empty() || !q2.empty());
    if (!q1.empty())
    {
        while (q1.size()>1)
        {
            q2.push(q1.front());
            q1.pop();
        }
        q1.pop();
    }
    else
    {
        while (q2.size()>1)
        {
            q1.push(q2.front());
            q2.pop();
        }
        q2.pop();
    }
}
template <typename T>
bool Stack<T>::empty()
{
    return q1.empty() && q2.empty();
}
template <typename T>
size_t Stack<T>::size()
{
    return q1.size() + q2.size();
}
template <typename T>
T& Stack<T>::top()  
{
    assert(!q1.empty() || !q2.empty());
    if (!q1.empty())
    {
        return q1.back();
    }
    else
    {
        return q2.back();
    }
}
template<typename T>  
class Stack  
{  
public:  
       void Push(const T& data);  
       void Pop();  
       T& Top();  
       size_t Size();  
       bool Empty();  
private:  
       queue<T> _q1;  
       queue<T> _q2;  
};  
template<typename T>  
void Stack<T>::Push(const T& data)  
{  
       向不空的队列里面插入数据  
       if (!_q2.empty())          //如果q2不为空  
       {  
              _q2.push(data);  
       }  
       else  
       {  
              _q1.push(data);  
       }  
}  
template<typename T>  
void Stack<T>::Pop()  
{  
       assert((_q1.size()+_q2.size()));    //两个队列不能同时为空  
       queue<T> *tmp1= NULL;    //记录不空的队列  
       queue<T> *tmp2 = NULL;    //记录空的队列  
       if (_q1.empty())          //如果_q1为空  
       {  
              tmp1 = &_q2;  
              tmp2 = &_q1;  
       }  
       else  
       {  
              tmp1 = &_q1;  
              tmp2 = &_q2;  
       }  
       while (tmp1->size() > 1)  
       {  
              tmp2->push(tmp1->front());  
              tmp1->pop();  
       }  
       tmp1->pop();  
}  
template<typename T>  
T& Stack<T>::Top()  
{  
       assert((_q1.size() + _q2.size()));    //两个队列不能同时为空  
       queue<T> *tmp1 = NULL;    //记录不空的队列  
       if (_q1.empty())          //如果_q1为空  
       {  
              tmp1 = &_q2;  
       }  
       else  
       {  
              tmp1 = &_q1;  
       }  
       return tmp1->back();         //返回不空的队列的尾部元素  
}  
template<typename T>  
size_t Stack<T>::Size()  
{  
       return (_q1.size() + _q2.size());  
}  
template<typename T>  
bool Stack<T>::Empty()  
{  
       return (_q1.empty() && _q2.empty());  
}  

用两个队列来回交换,使得能够先进后出就行。
4.判断元素出栈、入栈顺序的合法性。如:入栈的序列(1,2,3,4,5),出栈序列为
(4,5,3,2,1)是合法序列,入栈的序列(1,2,3,4,5),出栈序列为(1,5,3,2,4)是不合
法序列

要判断出栈入栈序列的合法性,最常见的方法就是模拟整个过程。

template<typename T>  
class StackLegality  
{  
public:  
       void SetInArray(const T& data);        //输入入栈序列  
       void SetOutAaary(const T& data);       //输入出栈序列  
       bool DecideLegality();  
private:  
       stack<T> s;  
       vector<T> InArray;  
       vector<T> OutArray;  
};  
template<typename T>  
void StackLegality<T>::SetInArray(const T& data)        //输入入栈序列  
{  
       InArray.push_back(data);  
}  
template<typename T>  
void StackLegality<T>::SetOutAaary(const T& data)       //输入出栈序列  
{  
       OutArray.push_back(data);  
}  
template<typename T>  
bool StackLegality<T>::DecideLegality()  
{  
       if (InArray.size() != OutArray.size())  //如果入栈序列与出栈序列的个数不相等,则一定不合法  
       {  
              return false;  
       }  
       int sz = (int)InArray.size();  
       int j = 0;  
       int i = 0;  
       while (i<sz)  
       {  
              if(i<sz&&s.empty())     //如果栈为空,则需要入栈  
              {  
                     s.push(InArray[i]);  
                     i++;  
              }  
              while (i<sz&&s.top() != OutArray[j])   //如果栈顶元素与出栈序列不相等,则一直入栈  
              {  
                     s.push(InArray[i]);  
                     i++;  
              }  
              while (!s.empty() && s.top() == OutArray[j])  
              {  
                     s.pop();  
                     j++;  
                     int i1 = i;  
                     int j1 = j;  
                     while (i1<sz)  
                     {  
                           if (i1<sz&&s.empty())     //如果栈为空,则需要入栈  
                           {  
                                  s.push(InArray[i1]);  
                                  i1++;  
                           }  
                           while (i1<sz&&s.top() != OutArray[j1])   //如果栈顶元素与出栈序列不相等,则一直入栈  
                           {  
                                  s.push(InArray[i1]);  
                                  i1++;  
                           }  
                           while (!s.empty() && s.top() == OutArray[j1])  
                           {  
                                  s.pop();  
                                  j1++;  
                           }  
                     }  
                     if (j1 == sz)  
                     {  
                           return true;  
                     }  
                     else  
                     {  
                           j--;  
                           while ((int)s.size()>=i)  
                           {  
                                  s.pop();  
                           }  
                           s.push(InArray[i-1]);  
                           s.push(InArray[i]);  
                           i++;  
                     }  
              }  
       }  
       if (j == sz)  
       {  
              return true;  
       }  
       else  
       {  
              return false;  
       }  
}  

思路:
所给定的两个序列数组,一个入栈序列,一个出栈序列。入栈序列比如说是(1,2,3,4,5);出栈序列比如说是(4,5,3,2,1);我们就首先入栈序列第一个元素入栈,这个时候让一个指针指向出栈序列第一个元素,如果出入栈以后,栈顶元素和指针所指的元素相等,那么就让栈顶元素出栈,让指针++,最后判定栈是否为空就好了,如果为空,就说明是合法的,如果不为空,就不合法。

//判断元素出栈、入栈顺序的合法性。
//如:入栈的序列(1,2,3,4,5)
//出栈序列为(4,5,3,2,1),是合法序列
//入栈序列(1,2,3,4,5),
//出栈序列为(1,5,3,2,4)是不合法序列


#pragma once
#include<iostream>
#include<cstdlib>
#include<cassert>
#include<stack>

using namespace std;

int j = 0;
bool JudgeStackSeq(int *InArr, int *OutArr, size_t sz)
{
    stack<int > s;
    int j = 0;
    int pos=0;
    for (size_t i = 0; i < sz; i++)
    {
        s.push(InArr[i]);


        while (!s.empty()&&s.top()==OutArr[j])
        {


            s.pop();
            j++;
        }

    }

    return s.empty();
}

5.一个数组实现两个栈
这里写图片描述
两种方法
一种是将数组按照奇偶顺序分成两部分,分别是奇数栈和偶数栈。另一种办法就是分别以数组的首部和尾部为栈底,实现一个栈。
例:
这里写图片描述
第一种:

template<typename T>  
class DoubleStack  
{  
public:  
       DoubleStack()  
              :_array(NULL)  
              , _size(0)  
              , _capacity(0)  
              , _top1(0)          //第一个栈的栈顶  
              , _top2(1){}        //第二个栈的栈顶  
       ~DoubleStack()  
       {  
              delete[] _array;  
       }  
public:  
       void Push(const T& data,int flag=0);  
       void Pop(int flag=0);  
       T& Top(int flag=0);  
       size_t Size(int flag=0);  
       bool Empty(int flag=0);  
private:  
       void CheckCapacity();  
private:  
       T* _array;  
       int _top1;       //第一个栈的栈顶  
       int _top2;       //第二个栈的栈顶  
       int _size;  
       int _capacity;  
};  
template<typename T>  
void DoubleStack<T>::CheckCapacity()  
{  
       if (_size >= _capacity)  
       {  
              int NewCapacity = 2 * _capacity + 2;  
              T* tmp = new T[NewCapacity];  
              for (int i = 0; i < _size; i++)  
              {  
                     tmp[i] = _array[i];  
              }  
              delete[] _array;  
              _array = tmp;  
              _capacity = NewCapacity;  
       }  
}  
template<typename T>  
T& DoubleStack<T>::Top(int flag)  
{  
       if (flag == 0)  
       {  
              assert(_top1>0);  
              return _array[_top1-2];  
       }  
       else  
       {  
              assert(_top2>1);  
              return _array[_top2 - 2];  
       }  
}  
template<typename T>  
void DoubleStack<T>::Push(const T& data, int flag)  
{  
       CheckCapacity();  
       if (flag == 0)  
       {  
              _array[_top1] = data;  
              _top1+= 2;  
              if (_top1 > _top2)  
              {  
                     _size += 2;  
              }  
       }  
       else  
       {  
              _array[_top2] = data;  
              _top2 += 2;  
              if (_top1<_top2)  
              {  
                     _size += 2;  
              }  
    }  
}  
template<typename T>  
void DoubleStack<T>::Pop(int flag)  
{  
       if (flag == 0)  
       {  
              assert(_top1>0);  
              _top1 -= 2;  
              if (_top1>_top2)  
              {  
                     _size-= 2;  
              }  
       }  
       else  
       {  
              assert(_top2>1);  
              _top2 -= 2;  
              if (_top1<_top2)  
              {  
                     _size -= 2;  
              }  
       }  
}  
template<typename T>  
size_t DoubleStack<T>::Size(int flag)  
{  
       if (flag ==0)  
       {  
              return (size_t)(_top1 / 2);  
       }  
       else  
       {  
              return (size_t)((_top2 - 1) / 2);  
       }  
}  
template<typename T>  
bool DoubleStack<T>::Empty(int flag)  
{  
       if (flag == 0)  
       {  
              return _top1 == 0;  
       }  
       else  
       {  
              return  _top2 == 1;  
       }  
}  

第二种:

template<typename T>  
class  DoubleStack  
{  
public:  
       DoubleStack()  
              :_array(NULL)  
              , _capacity(0)  
              , _top1(0)  
              , _top2(0){}  
       ~DoubleStack()  
       {  
              delete[] _array;  
       }  
public:   
       void Push(const T& data,int flag = 0);  
       T& Top(int flag = 0);  
       void Pop(int flag = 0);  
       size_t Size(int flag=0);  
       bool Empty(int flag = 0);  
private:  
       void CheckCapacity();  
private:  
       T*  _array;  
       int _capacity;  
       int _top1;  
       int _top2;  
};  
template<typename T>  
void DoubleStack<T>::CheckCapacity()  
{  
       if (_top1==_top2)  
       {  
              int NewCapacity = 2 *_capacity + 4;  
              T *tmp =new T[NewCapacity];  
              for (int i = 0; i < _top1; i++)  
              {  
                     tmp[i] = _array[i];  
              }  
              int j = _capacity - 1;  
              for (int i = NewCapacity - 1; j>_top2; --i,--j)  
              {  
                     tmp[i] = _array[j];  
              }  
              delete[] _array;  
              _array = tmp;     
              size_t count =0;      //求出第二个栈的元素的个数  
              if (_capacity != 0)  
              {  
                     count = _capacity - 1 - _top2;  
              }  
              _capacity = NewCapacity;  
              _top2 =_capacity-1-count;     //改变_top2的值      
              cout << _capacity << endl;  
       }  
}  
template<typename T>  
void DoubleStack<T>::Push(const T& data,int flag = 0)  
{  
       CheckCapacity();  
       if (flag == 0)  
       {  
              _array[_top1++] = data;  
       }  
       else  
       {  
              _array[_top2--] = data;  
       }  
}  
template<typename T>  
T& DoubleStack<T>::Top(int flag = 0)  
{  
       if (flag == 0)  
       {  
              assert(_top1>0);  
              return _array[_top1 - 1];  
       }  
       else  
       {  
              assert(_top2<_capacity-1);  
              return _array[_top2+1];  
       }  
}  
template<typename T>  
void DoubleStack<T>::Pop(int flag = 0)  
{  
       if (flag == 0)  
       {  
              assert(_top1>0);  
              _top1--;  
       }  
       else  
       {  
              assert(_top2<_capacity - 1);  
              _top2++;  
       }  
}  
template<typename T>  
size_t DoubleStack<T>::Size(int flag = 0)  
{  
       if (flag == 0)  
       {  
              return (size_t)_top1;  
       }  
       else  
       {  
              return (size_t)(_capacity-1-_top2);  
       }  
}  
template<typename T>  
bool DoubleStack<T>::Empty(int flag = 0)  
{  
       if (flag == 0)  
       {  
              return _top1 == 0;  
       }  
       else  
       {  
              return _top2 == (_capacity - 1);  
       }  
}  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值