本文是【程序员代码面试指南(第二版)学习笔记】C#版算法实现系列之一,用C#实现了《程序员代码面试指南》(第二版)栈和队列中的如何仅用递归函数和栈操作逆序一个栈。文中的示意图也都来自此书。
只用递归函数和栈,实现将一个栈内的元素逆序化。
概述:需要一个函数,可以做到将栈底元素取出而其余元素不变,记为函数一;还需要一个函数实现逆序,记为函数二。
函数一:
1、每次进入函数,只要有元素就要取出来一个,如果取出以后发现栈为空了,那么说明取出的元素是最后一个元素,根据需求,就需要将这一元素返回。
2、只要还没有将全部元素取出,那么就要递归进行下次取元素操作。当递归到最后,那个返回值就是最底端的元素,将其赋值给last。
3、赋值结束后,也即递归到了最底层,那么就应该将原来不在最底部的元素原封不动放回去。
4、最后放好元素后就可以返回结果了。
函数二:
1、实现逆序需要每次进入函数二的时候都调用函数一来提取出最底部的元素,并将取出的元素赋给num。如果栈空了,那么就不需要提取了,直接返回。
2、放入元素的时机应该是在调用函数一将所有元素都提取出来之后,所以要进行递归操作,不断取出栈底元素。
3、全部取出后,取出的顺序和将要放入的顺序正好是相反的(取出是外层递归到内层递归函数的顺序,放入是内层到外层的顺序),所以这时逐个放入元素便完成了栈的逆序。
public static int GetAndRemoveLastElement(Stack<int> nums) {
int ret = nums.Pop();
// 最后一个元素找到以后, 就将最后一个元素返回
if (nums.Count == 0) {
return ret;
}
// 有上一个元素就每次都找上一个元素
int last = GetAndRemoveLastElement(nums);
// 运行到这里说明最后一个元素已经取出, 那么就该将除了最后一个元素以外的元素再放回去
nums.Push(ret);
// 最终返回的是最后一个元素
return last;
}
public static void Reverse(Stack<int> nums) {
// 栈为空就直接结束
if (nums.Count == 0) {
return;
}
// 每次都取出目前最底部的元素
int num = GetAndRemoveLastElement(nums);
// 递归使得从栈最底部到最顶部逐个取出
Reverse(nums);
// 此时逐个放入的顺序便是最顶部到最底部的顺序
nums.Push(num);
}