与栈相关的问题

1.设计一个栈,在其基础功能的基础上,设计一个getMin方法,每次调用时返回当前栈内的最小值。

要求:时间复杂度为O(1),可使用现成的栈结构。

思路:设计该栈有两个栈,一个保存正常数据stackData,一个保存正常数据中的较小值stackMin。在新数据压入栈时,比较其与stackMin中栈顶元素,如果新数据小于等于stackMin栈顶,则将其插入stackMin,否则舍弃。同样,在stackData出栈时,检查出栈元素和stackMin的栈顶元素是否相等,相等则stackMin也同样出栈,这样就保证了stackMin的顶部始终存储的是stackData中的最小元素。

如图压入3,4,5,1,2,1

 

 代码如下

#include<iostream>
#include<assert.h>
#include<stack>
using namespace std;
template <class T>
class mystack
{
	private:
		stack<T> stackData;
		stack<T> stackMin;
	public:
		void push(T newNum);
		bool pop();
		T getMin();
};

	template<class T>
void mystack<T>::push(T newNum)
{
	stackData.push(newNum);
	if(stackMin.size() != 0)
	{
		if(stackMin.top() >= newNum)//在stackMin不为空时,新元素小于stackMin栈顶,则压入stackMin
			stackMin.push(newNum);
	}
	else
		stackMin.push(newNum);
	return;
}

	template<class T>
bool mystack<T>::pop()
{
	if(stackData.size() == 0)
		return false;
	if(stackData.top() == stackMin.top())
	{
		stackData.pop();
		stackMin.pop();
	}
	else
		stackData.pop();
	return true;
}

	template<class T>
T mystack<T>::getMin()
{
	assert(stackMin.size() != 0);
	return stackMin.top();

}


int main()
{
	mystack<int> ms;
	for(int i=10; i>0; --i)
		ms.push(i);
	for(int i=0; i<10; ++i)
	{
		cout<<"mystack min = "<<ms.getMin()<<endl;
		ms.pop();
	}
	return 0;
}

 

2.编写一个类,使用两个栈实现队列的基本功能poll,peek,add

(poll出队并返回队头元素,peek仅返回队头元素)

思路如下,设计两个栈,stackpush和stackpop,当要入队时,则向stackpush中压栈,当要出队时,将元素从stackpush弹出并压入stackpop中,这样从stackpop中弹出的即为队头元素。用图来说明

 

 如图我们就可以清楚地看出来,如果要add元素时,队列中的元素应在stackpush中,当要poll或peek元素时,元素应该在stackpop中,所以,用一个flag来表明现在元素所在位置,0为队列为空,1表示元素在stackpush中,-1表示元素在stackpop中,这样每当要入队或出队时先查看当前元素所在位置,这样就知道是否需要将元素倒过来。

#include<iostream>
#include<assert.h>
#include<stack>
using namespace std;

template<class T>
class myqueue
{
	private:
		stack<T> stackpush;
		stack<T> stackpop;
		short flag;
	public:
		myqueue():flag(0){}
		void add(T input);
		T poll();
		T peek();
};

	template<class T>
void myqueue<T>::add(T input)
{
	if(flag == -1)//元素在stackpop中,先把元素倒回stackpush
	{
		while(!stackpop.empty())
		{
			stackpush.push(stackpop.top());
			stackpop.pop();
		}
	}
	stackpush.push(input);
	flag = 1;
	return;
}

	template<class T>
T myqueue<T>::poll()
{
	if(stackpush.size()==0 &&stackpop.size()==0)
		exit(1);
	if(flag == 1)//元素在stackpush中,先把元素倒回stackpop
	{
		while(!stackpush.empty())
		{
			stackpop.push(stackpush.top());
			stackpush.pop();
		}
	}

	T res = stackpop.top();
	stackpop.pop();
	flag = -1;
	return res;
}

	template<class T>
T myqueue<T>::peek()
{
	if(stackpush.size()==0 &&stackpop.size()==0)
		exit(1);
	if(flag == 1)
	{
		while(!stackpush.empty())
		{
			stackpop.push(stackpush.top());
			stackpush.pop();
		}
	}

	T res = stackpop.top();
	flag = -1;
	return res;
}
int main()
{
	myqueue<int> mq;
	for(int i=0; i<10; ++i)
		mq.add(i);
	for(int i=0; i<20; ++i)
	{
		if(i%2)
			cout<<"poll = "<<mq.poll()<<endl;
		else
			cout<<"peek = "<<mq.peek()<<endl;
	}
	for(int i=0; i<10; ++i)
		mq.add(i);
	for(int i=0; i<20; ++i)
	{
		if(i%2)
			cout<<"poll = "<<mq.poll()<<endl;
		else
			cout<<"peek = "<<mq.peek()<<endl;
	}
	return 0;
}

 

3.如何仅用递归操作来逆序一个栈

首先我们需要得到栈底元素并将其删除,然后再进行逆序即可

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

	template<class T>
int getAndRemoveLastElement(stack<T> *st)
{
	T res = st->top();
	st->pop();
	if(st->size() == 0)//递归循环,栈为空时说明到达栈底,返回栈底元素
		return res;
	else
	{
		T last = getAndRemoveLastElement(st);
		st->push(res);
		return last;
	}
}

	template<class T>
void reverse(stack<T> *st)
{
	if(st->size() == 0)
		return;
	else
	{
		T i = getAndRemoveLastElement(st);//依次抽取栈底元素
		reverse(st);//直到为空
		st->push(i);//然后再进行压栈
	}
}

int main()
{
	stack<int> st;
	for(int i=0; i<10; ++i)
		st.push(i);
	reverse(&st);
	for(int i=0; i<10; ++i)
	{
		cout<<st.top()<<" ";
		st.pop();
	}
	cout<<endl;
	return 0;
}

 

posted @ 2020-05-13 10:56  C_hp  阅读(212)  评论(0编辑  收藏  举报