颠倒栈

题目:用递归颠倒一个栈。例如输入栈{1, 2, 3, 4, 5}1在栈顶。颠倒之后的栈为{5, 4, 3, 2, 1}5处在栈顶。

分析:乍一看到这道题目,第一反应是把栈里的所有元素逐一pop出来,放到一个数组里,然后在数组里颠倒所有元素,最后把数组中的所有元素逐一push进入栈。这时栈也就颠倒过来了。颠倒一个数组是一件很容易的事情。不过这种思路需要显示分配一个长度为O(n)的数组,而且也没有充分利用递归的特性。

我们再来考虑怎么递归。我们把栈{1, 2, 3, 4, 5}看成由两部分组成:栈顶元素1和剩下的部分{2, 3, 4, 5}。如果我们能把{2, 3, 4, 5}颠倒过来,变成{5, 4, 3, 2},然后在把原来的栈顶元素1放到底部,那么就整个栈就颠倒过来了,变成{5, 4, 3, 2, 1}

接下来我们需要考虑两件事情:一是如何把{2, 3, 4, 5}颠倒过来变成{5, 4, 3, 2}。我们只要把{2, 3, 4, 5}看成由两部分组成:栈顶元素2和剩下的部分{3, 4, 5}。我们只要把{3, 4, 5}先颠倒过来变成{5, 4, 3},然后再把之前的栈顶元素2放到最底部,也就变成了{5, 4, 3, 2}

至于怎么把{3, 4, 5}颠倒过来……很多读者可能都想到这就是递归。也就是每一次试图颠倒一个栈的时候,现在栈顶元素pop出来,再颠倒剩下的元素组成的栈,最后把之前的栈顶元素放到剩下元素组成的栈的底部。递归结束的条件是剩下的栈已经空了。这种思路的代码如下:

template<typename T>void ReverseStack(std::stack<T>& stack)

{

   if(!stack.empty())

    {

        T top = stack.top();

        stack.pop();

        ReverseStack(stack);

        AddToStackBottom(stack, top);

    }

}

我们需要考虑的另外一件事情是如何把一个元素e放到一个栈的底部,也就是如何实现AddToStackBottom。这件事情不难,只需要把栈里原有的元素逐一pop出来。当栈为空的时候,push元素e进栈,此时它就位于栈的底部了。然后再把栈里原有的元素按照pop相反的顺序逐一push进栈。

注意到我们在push元素e之前,我们已经把栈里原有的所有元素都pop出来了,我们需要把它们保存起来,以便之后能把他们再push回去。我们当然可以开辟一个数组来做,但这没有必要。由于我们可以用递归来做这件事情,而递归本身就是一个栈结构。我们可以用递归的栈来保存这些元素。

基于如上分析,我们可以写出AddToStackBottom的代码:

template<typename T>void AddToStackBottom(std::stack<T>& stack, T t)

{

   if(stack.empty())

    {

        stack.push(t);

    }

   else

    {

        T top = stack.top();

        stack.pop();

        AddToStackBottom(stack, t);

        stack.push(top);

    }

}


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

template<typename T> void AddToStackBottom(stack<T>& s, T t)
{
	if(s.empty())
		s.push(t);
	else
	{
		T top=s.top();
		s.pop();
		AddToStackBottom(s, t);
		s.push(top);
	}
}

template<typename T> void ReverseStack(stack<T> & s)
{
	if(!s.empty())
	{
		T top=s.top();
		s.pop();
		ReverseStack(s);
		AddToStackBottom(s, top);
	}
}

void main()
{
	stack<int> mystack;
	mystack.push(1);
	mystack.push(2);
	mystack.push(3);
	mystack.push(4);
	mystack.push(5);

	ReverseStack(mystack);

	while(!mystack.empty())
	{
		cout<<mystack.top();
		mystack.pop();
	}

	cout<<endl;
		
}

--------------------

//============================================================================
// Name        : 100题之颠倒栈.cpp
// Author      :
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================
#include <iostream>
#include<stack>
using namespace std;
void AddToStackBottom(stack<int>&s, int top)
{
	if(s.empty())
	{
		s.push(top);
		return;
	}
	int top1=s.top();
	s.pop();
	AddToStackBottom(s, top);
	s.push(top1);
}
void reverseStack(stack<int>&s)
{
	if(s.empty())
		return;
	if(s.size()==1)
		return;
	int top=s.top();
	s.pop();
	reverseStack(s);
	AddToStackBottom(s, top);
}

int main() {
	stack<int>s;
	s.push(5);
	s.push(4);
	s.push(3);
	s.push(2);
	s.push(1);
	reverseStack(s);
	cout<<s.size()<<endl;
	while(!s.empty())
	{
		cout<<s.top()<<" ";
		s.pop();
	}
	return 0;
}



评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值