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);
}
}