19-递归的理解、场景

不管现实多么惨不忍睹,都要持之以恒地相信,这只是黎明前短暂的黑暗而已。不要惶恐眼前的难关迈不过去,不要担心此刻的付出没有回报,别再花时间等待天降好运。真诚做人,努力做事!你想要的,岁月都会给你。19-递归的理解、场景,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

一、递归

🌭🌭🌭在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数

核心思想是把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解

一般来说,递归需要有边界条件、递归前进阶段和递归返回阶段。当边界条件不满足时,递归前进;当边界条件满足时,递归返回

下面实现一个函数 pow(x, n),它可以计算 x 的 n 次方

function pow(x,n){
	let result = 1;
	for(let i = 0;i < n;i++){
		result = result * x;	
	}
	return result;
}

递归的方式

function pow(x,n){
	if(n == 1){
		return x;
	}else{
		return x * pow(x,n - 1)	
	}
}

pow(x,n)被调用时,执行分为两个分支

在这里插入图片描述
也就是说 pow 递归地调用自身 直到 n == 1

在这里插入图片描述
计算 pow(2,4),递归变体经过以下步骤:

pow(2,4) = 2 * pow(2,3)
pow(2,3) = 2 * pow(2,2)
pow(2,2) = 2 * pow(2,1)
pow(2,1) = 2

递归将函数调用简化为一个更简单的函数调用,然后再将其简化为一个更简单的函数,以此类推,直到结果

二、尾递归

尾递归,即在函数尾位置调用自身。一种特殊情形,即在尾部直接调用自身

特征:

  • 在尾部调用的是 函数自身
  • 可通过优化,使得计算仅占用常量栈空间

在递归调用的过程当中系统为每一层的返回点、局部量等开辟了栈来存储,递归次数过多容易造成栈溢出

这时候,我们就可以使用尾递归,即一个函数中所有递归形式的调用都出现在函数的末尾,对于尾递归来说,由于只存在一个调用记录,所以永远不会发生”栈溢出”错误

实现一下阶乘,如果用普通的递归,如下

function factorial(n){
	if(n === 1) return 1;
	return n * factorial(n - 1);
}
factorial(5)

如果n等于5,这个方法要执行5次,才返回最终的计算表达式,这样每次都要保存这个方法,就容易造成栈溢出

如果我们使用尾递归

function factorial(n,total){
	if(n === 1) return total;
	return factorial(n - 1,n * total);
}
factorial(5,1)

可以看到,每一次返回的就是一个新的函数,不带上一个函数的参数,也就不需要储存上一个函数了。尾递归只需要保存一个调用栈

二、应用场景

数组求和:

const arr = [1,2,3]
function sumArray(arr,total){
	if(arr.length === 1){
		return total
	}
	return sumArray(arr,total + arr.pop())
}
sumArray(arr,1)
// 数组扁平化
let a = [1,2,3, [1,2,3, [1,2,3]]];
// 变成 [1,2,3,1,2,3,1,2,3]
function flat(arr = [],result = []){
	arr.forEach(v =>{
			if(Array.isArray(v)){
			   result = result.concat(flat(v,[]))
		}else{
			result.push(v)	
		}
	})
	return result
}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/163299.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!