栈与队列的各种操作
1.用两个栈实现队列
2.包含min函数的栈
3.栈的压入、弹出序列
4.栈的压入、弹出序列
5.仅用递归函数和栈操作逆序一个栈
6.用一个栈实现另一个栈的排序
7.滑动窗口的最大值
1.用两个栈实现一个队列。队列的声明如下,请实现它的两个函数appendTail 和 deleteHead,分别完成在队列尾部插入节点和在队列头部删除结点的功能。
template class CQueue{
public:
CQueue(void);
~CQueue(void);
void appendTail (const T& node);
T deleteHead();
private:
stack stack1;
stack stack2;
}
template void CQueue::qppendTail(const T& element)
{
stack1.push(element);
}
templateT CQueue::deleteHead()
{
if (stack2.size()<=0){
while(stack1.size() >0)
{
T& data = stack1.top();
stack1.pop();
stack2.push(data);
}
}
if (stack2.size() == 0)
throw new exception("queue is empty");
T head = stack2.top();
stack2.pop();
return head;
}
2.定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的min函数。在该栈中,调用min、push及pop的时间复杂度都是O(1)。
下面代码中,m_data是数据栈,而 m_min是辅助栈。
templatevoid StackWithMin::push(const T& value)
{
m_data.push(value);
if (m_min.size() == 0 || value < m_min.top())
m_min.push(value);
else
m_min.push(m_min.top());
}
templatevoid StackWithMin::pop()
{
assert(m_data.size() > 0 && m_min.size() > 0);
m_data.pop();
m_min.pop();
}
templatevoid StackWithMin::min() const
{
assert(m_data.size() > 0 && m_min.size()>0);
return m_min.top();
}
3.输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压栈序列,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。
bool IsPopOrder(const int *pPush, const int *pPop, int nLength)
{
bool bPossible = false;
if (pPush != NULL && pPop != NULL && nLength > 0)
{
const int *pNextPush = pPush;
const int *pNextPop = pPop;
stackstackData;
while (pNextPop - pPop < nLength)
{
while (stackData.empty() || stackData.top() != *pNextPop)
{
if (pNextPush - pPush == nLength)
break;
stackData.push(*pNextPush);
pNextPush++;
}
if (stackData.top() != *pNextPop)
break;
stackData.pop();
pNextPop++;
}
if (stackData.empty() && pNextPop - pPop == nLength)
bPossible = true;
}
return bPossible;
}
4.栈的压入、弹出序列
题目:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压栈序列,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。
bool IsPopOrder(const int *pPush, const int *pPop, int nLength)
{
bool bPossible = false;
if (pPush != NULL && pPop != NULL && nLength > 0)
{
const int *pNextPush = pPush;
const int *pNextPop = pPop;
stackstackData;
while (pNextPop - pPop < nLength)
{
while (stackData.empty() || stackData.top() != *pNextPop)
{
if (pNextPush - pPush == nLength)
break;
stackData.push(*pNextPush);
pNextPush++;
}
if (stackData.top() != *pNextPop)
break;
stackData.pop();
pNextPop++;
}
if (stackData.empty() && pNextPop - pPop == nLength)
bPossible = true;
}
return bPossible;
}
5.一个栈依次压入1,2,3,4,5,那么从栈顶到栈低分别为5,4,3,2,1。将这个栈转置后,从栈顶到栈低为1,2,3,4,5,也就是实现栈中元素的逆序,但是只能用递归函数来实现,不能用其他数据结构。
int getAndRemoveLast(stack&s) {
int res = s.top();
s.pop();
if (s.empty())return res;
else {
int last = getAndRemoveLast(s);
cout << last << endl;
s.push(res);
return last;
}
}
void reverse(stack&s) {
if (s.empty())return;
int i = getAndRemoveLast(s);
reverse(s);
s.push(i);
}
6. 一个栈中元素类型为整型,现在想将该栈从顶到底按从大到小的顺序排序,只许申请一个栈。除此之外,可以申请新的变量,但不能申请额外的数据结构。
void stackSort(stack&s) {
stackaux;
while (!s.empty()){
int res = s.top();
s.pop();
while (!aux.empty() && res < aux.top()) {
s.push(aux.top());
aux.pop();
}
aux.push(res);
}
while (!aux.empty()) {
s.push(aux.top());
aux.pop();
}
}
7. 给定一个数组和滑动窗口的大小,请找出所有滑动窗口里的最大值。例如,如果输入数组{2 3 4 2 6 2 5 1}及滑动窗口的大小3,那么一共存在6个滑动窗口,它们的最大值分别是{4 4 6 6 6 5}。
vectorfindMaxValue2(vectorv, int n) {
vectorres;
if (v.size() >= n && n >= 1) {
dequeindex;
for (int i = 0; i < n; i++) {
while (!index.empty() && v[i] >= v[index.back()])
index.pop_back();
index.push_back(i);
}
for (int i = n; i < v.size(); ++i) {
res.push_back(v[index.front()]);
while (!index.empty() && v[i] >= v[index.back()])
index.pop_back();
if (!index.empty() && index.front() <= i - n)
index.pop_front();
index.push_back(i);
}
res.push_back(v[index.front()]);
}
return res;
}