39.递归颠倒栈

http://zhedahht.blog.163.com/blog/static/25411174200943182411790/

分析:乍一看到这道题目,第一反应是把栈里的所有元素逐一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出来,再颠倒剩下的元素组成的栈,最后把之前的栈顶元素放到剩下元素组成的栈的底部。递归结束的条件是剩下的栈已经空了。这种思路的代码如下:


// Reverse a stack recursively in three steps:
// 1. Pop the top element
// 2. Reverse the remaining stack
// 3. Add the top element to the bottom of the remaining stack
template<typename T>
void ReverseStack(std::stack<T>& stack)
{
if (stack.empty())
return;

T top = stack.top();
stack.pop();
ReverseStack(stack);
AddToStackBottom(stack, top);
}

// Add an element to the bottom of a stack:
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);
}
}

39.递归颠倒栈

时间: 2024-09-30 16:24:54

39.递归颠倒栈的相关文章

C#=&gt;递归反转栈

原理,递归反转栈 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Threading.Tasks; 5 6 namespace StacksReverse 7 { 8 public class Program 9 { 10 public void Main(string[] args) 11 { 12 StacksReverses stacksReverses = ne

【编程题目】颠倒栈☆

66.颠倒栈(栈).题目:用递归颠倒一个栈.例如输入栈{1, 2, 3, 4, 5},1 在栈顶.颠倒之后的栈为{5, 4, 3, 2, 1},5 处在栈顶. 思路:我自己没做出来,因为总觉得用不上递归.看了网上答案http://blog.csdn.net/cxllyg/article/details/7655935 根据里面的思路 自己照着写了一遍 /* 66.颠倒栈(栈). 题目:用递归颠倒一个栈.例如输入栈{1, 2, 3, 4, 5},1 在栈顶. 颠倒之后的栈为{5, 4, 3, 2,

微软算法100题66 颠倒栈

66.颠倒栈.题目:用递归颠倒一个栈.例如输入栈{1, 2, 3, 4, 5},1 在栈顶.颠倒之后的栈为{5, 4, 3, 2, 1},5 处在栈顶. 思路: 首先想到的是再创建一个新栈,用来接收旧栈的数据,但这样空间复杂度是o(n),可不可以用原有的栈完成颠倒的操作呢? 假设栈里只有两个元素1,2,pop出1后,栈里剩下2,我们所做的是把2再弹出,将1push回栈,再push2, 比较重要的是往回push的过程,如果判断栈里还有剩余元素,则需要把剩余元素先都pop出栈,再push元素入栈,这

函数递归与栈的关系

首先通过反汇编语言,我们来了解一下最简单的递归函数与栈之间的关系. 如何获得反汇编语言,在visual studio 2008中,在debug环境下,在debug/windows/disassembly中可以查看反汇编之后的语言.现在我们看一下阶乘n!的实现 其C语言实现代码如下 [cpp] view plaincopy #include <stdio.h> int factorial(int n); int main(void) { int fact; fact = factorial(4)

Python旅途——函数的递归和栈的使用

Python--函数之递归.栈的使用 今天主要和大家分享函数的递归,同时引入一个新的概念--栈 1.递归 1.定义 函数的递归指的就是函数自己调用自己,什么是函数自己调用自己呢?我们来看一个栗子: 这里给大家一个数学中的一个数列:斐波那契数列 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,377,610,987,1597,2584,4181,6765,10946,17711,28657,46368,它指的是前两项的和等于第三项,那么我们对于这

NYOJ305 表达式求值(递归or栈)

题目意思: http://acm.nyist.net/JudgeOnline/problem.php?pid=305 Dr.Kong设计的机器人卡多掌握了加减法运算以后,最近又学会了一些简单的函数求值,比如,它知道函数min(20,23)的值是20 ,add(10,98) 的值是108等等.经过训练,Dr.Kong设计的机器人卡多甚至会计算一种嵌套的更复杂的表达式. 假设表达式可以简单定义为: 1. 一个正的十进制数 x 是一个表达式. 2. 如果 x 和 y 是 表达式,则 函数min(x,y

打印完整的递归调用栈

之前在写0-1背包问题的递归解法时,想要弄出完整的递归栈.尝试了使用debug工具手工追踪并画出调用栈,发现太麻烦了,又试了一下使用visual studio的code map功能,发现对于递归,它只会显示递归函数不断调用自己,并不会自动展开成为树的形式.所以我就使用了最简陋的办法,就是自己写了一个类,依赖C++的constructor和destructor来自动将栈输入到一个vector中,并且在main函数结束的地方添加一个语句将其内容输出到文件中. 这里使用了一些C++11的特性,我使用m

只使用递归实现栈的逆序操作

2017-06-23 20:36:02 刚开始思考这个问题的时候陷入了一个误区,就是以为只能用一个递归完成. 然而事实上,可以使用两个递归来完成这个功能. 具体思考是这样的,首先递归其实是将问题规模缩小了,每次处理更小的问题.针对这题来说,更小的问题应该是去除底部那个数后的逆序再加上最后的数. 当然,你可能会问,什么不是去掉最上面的数,然后将它再放到最前面,理由很简单,栈是一种后进先出的数据结构,这种类型的数据结构适合的是在尾部添加数据,而非在首部添加数据,所以更清晰的或者说更适合栈的操作是先把

二叉树遍历,递归,栈,Morris

一篇质量非常高的关于二叉树遍历的帖子,转帖自http://noalgo.info/832.html 二叉树遍历(递归.非递归.Morris遍历) 2015年01月06日 |  分类:数据结构 |  标签:二叉树遍历 |  评论:8条评论 |  浏览:6,603次 二叉树遍历是二叉树中最基本的问题,其实现的方法非常多,有简单粗暴但容易爆栈的递归算法,还有稍微高级的使用栈模拟递归的非递归算法,另外还有不用栈而且只需要常数空间和线性时间的神奇Morris遍历算法,本文将对这些算法进行讲解和实现. 递归