递归函数的由来可以追溯到数学中的递归概念和数学归纳法。
在数学中,递归是指通过定义基本情况和递推公式,将一个问题分解为更简单的、与原问题具有相同结构的子问题,并用子问题的解来构建原问题的解。递归的思想在解决一些数学问题时非常有用。
当计算机科学发展起来后,人们将递归思想应用到程序设计中,形成了递归函数的概念。递归函数是一种能够调用自身的函数。 递归函数的使用可以有效地解决一些需要重复执行相似任务或处理具有递归结构的问题。
递归函数的设计通常包括两部分:
基本情况(边界条件):定义问题的最简单情况和对应的解,作为递归的终止条件。
递推公式(递归关系):描述问题和子问题之间的联系,通过递归调用函数本身来解决规模较小的子问题。
递归函数的执行过程中,每次调用都会创建一个新的函数上下文(包括参数、局部变量等),并将其压入执行栈。递归函数通过不断调用自身,并处理更小规模的子问题,直到达到基本情况为止,然后逐步返回结果,并依次弹出执行栈中的上下文,完成整个递归过程。递归函数在实际编程中有广泛的应用,例如树的遍历、图的搜索、排列组合、动态规划等领域。但需要注意的是,递归函数的设计要合理,避免无限递归或重复计算,以确保程序的正确性和效率。
假设下方的数据是我们从接口中获取到的
数据结构: 每个元素都具有
id
、pid
、title
和money
属性,其中id
是每个元素的唯一标识,pid
是父级元素的id
,title
是该元素的标题,money
是一些金额。
var temp = [
{
"id": 1,
"pid": 0,
"title": "一档",
"money": "666.00"
},
{
"id": 2,
"pid": 0,
"title": "二档",
"money": "1900.00"
},
{
"id": 3,
"pid": 1,
"title": "一档1级",
"money": "1800.00"
},
{
"id": 4,
"pid": 0,
"title": "三档",
"money": "2000.00"
},
{
"id": 5,
"pid": 0,
"title": "四档",
"money": "2200.00"
},
{
"id": 6,
"pid": 5,
"title": "四档1级",
"money": "2200.00"
},
{
"id": 7,
"pid": 2,
"title": "二档1级",
"money": "3700.00"
},
{
"id": 8,
"pid": 4,
"title": "三档1级",
"money": "2000.00"
}]
首先将拿到的数据进行处理
递归构建树: 函数 getTree(list, pid, data)
被调用时,它的目标是在 data
数组中构建一个树状结构。参数 list
是原始数据数组,pid
是当前节点的父级 ID,data
是用来存储构建的树状结构的数组。
//处理好的数据
let res = getTree(temp,0,[]);
console.log(res);//打印观察
先获取到所有的以及数据
获取一级节点: 使用 for...of 循环遍历原始数据 list,查找所有父级 ID 等于当前 pid 的元素,然后将这些元素添加到 data 数组中,这些元素就成为了一级节点。
获取子级节点: 对于每个一级节点,使用 for...of 循环遍历 data,为每个一级节点添加一个空数组 children,然后再次调用 getTree 函数,将当前一级节点的 id 作为新的 pid,并传入该一级节点的 children 数组。
//处理数据方法
function getTree(list,pid,data){
//获取所有一级
for(let item of list){
if(item.pid == pid){
data.push(item);
}
}
return data;
}
获取二级及三级数据
删除空的 children
属性: 在每个一级节点的循环中,如果它没有子级节点(即 children
数组为空),则删除该属性,以使最终结果更清晰。
//获取子级
for(let i of data){
i.children = [];
getTree(list,i.id,i.children);//递归调用
if(i.children.length == 0){
delete i.children;
}
}
返回树状数据结构: 函数返回构建好的树状结构,即 data
数组,其中每个元素都带有 children
属性,表示它的子级节点。
日志输出: 最后,你使用 console.log(res)
将构建好的树状结构打印到控制台。
逻辑整体代码
//处理好的数据
let res = getTree(temp,0,[]);
console.log(res);//打印观察
//处理数据方法
function getTree(list,pid,data){
//获取所有一级
for(let item of list){
if(item.pid == pid){
data.push(item);
}
}
//获取子级
for(let i of data){
i.children = [];
getTree(list,i.id,i.children);//递归调用
if(i.children.length == 0){
delete i.children;
}
}
return data;
}
效果如下: