递归(英语:Recursion),在数学和计算机科学中是指在函数的定义中使用函数自身的方法,在计算机科学中还额外指一种通过重复将问题分解为同类的子问题而解决问题的方法。
*递归思想:将未知的问题缩小,直到访问到已知问题便开始返回值,最后解决我们的问题。
递归的基本思想是某个函数直接或者间接地调用自身,这样原问题的求解就转换为了许多性质相同但是规模更小的子问题。求解时只需要关注如何把原问题划分成符合条件的子问题,而不需要过分关注这个子问题是如何被解决的。
*递归特点:代码简洁明了,但不符合人类思考逻辑,深入理解稍难,体现了数学的美。
递归代码最重要的两个特征:结束条件和自我调用。自我调用是在解决子问题,而结束条件定义了最简子问题的答案。
int func(传入数值) {
if (终止条件) return 最小子问题解;
return func(缩小规模);
}
递归:
1.结构清晰,可读性强
递归实现归并排序
template <typename T>
void merge_sort(vector<T> a, int front, int end) {
if (front >= end) return;
int mid = front + (end - front) / 2;
merge_sort(a, front, mid);
merge_sort(a, mid + 1, end);
merge(a, front, mid, end);
}
2.练习分析问题的结构
递归在求解复杂问题的时候可以起到非常重要的作用————分解复杂问题。
递归的缺点:
在程序执行中,递归是利用堆栈来实现的。每当进入一个函数调用,栈就会增加一层栈帧,每次函数返回,栈就会减少一层栈帧。而栈不是无限大的,当递归层数过多时,就会造成 栈溢出 的后果。
有时候递归处理是高效的,有时候是低效的
递归的优化:
搜索优化和记忆化搜索
比较初级的递归实现可能递归次数太多,容易超时。这时需要对递归进行优化。
写递归的要点
明白一个函数的作用并相信它能完成这个任务,千万不要跳进这个函数里面企图探究更多细节, 否则就会陷入无穷的细节无法自拔,人脑能压几个栈啊。
区别
递归与枚举的区别
递归和枚举的区别在于:枚举是横向地把问题划分,然后依次求解子问题;而递归是把问题逐级分解,是纵向的拆分。
递归与分治的区别
递归是一种编程技巧,一种解决问题的思维方式;分治算法很大程度上是基于递归的,解决更具体问题的算法思想。
参考oiwiki递归 & 分治 - OI Wiki (oi-wiki.org)