
本文介绍如何对具有嵌套 children 数组的树形对象数组进行深度感知排序:先按最大嵌套深度降序排列,深度相同时按直接子节点数量降序排列,并递归应用于每一层。
本文介绍如何对具有嵌套 children 数组的树形对象数组进行深度感知排序:先按最大嵌套深度降序排列,深度相同时按直接子节点数量降序排列,并递归应用于每一层。
在处理树形数据(如菜单、组织架构、文件目录)时,常需按“结构复杂度”重新排序——即优先展示嵌套更深、分支更丰富的节点。本教程提供一种纯 JavaScript 递归方案,无需第三方库,支持任意深度嵌套,并严格满足两大排序规则:
- 主序:按最大嵌套深度(depth)降序 —— 深度越大越靠前;
- 次序:深度相同时,按当前节点的 children.length 降序 —— 子节点越多越靠前。
✅ 关键洞察:所谓“深度”,指从当前节点向下延伸的最长路径长度(叶子节点深度为 0,仅含空 children 的节点深度为 1),而非层级索引。
核心实现逻辑
我们分两步完成:
- 第一步:标注深度 —— 使用 setDepth() 递归计算每个节点的 depth 属性(表示其子树最大深度);
- 第二步:原地排序 —— 使用 sort() 递归排序:先按 depth 降序,再按 children.length 降序,最后清理临时属性。
以下是完整、可直接运行的代码:
立即学习“Java免费学习笔记(深入)”;
function setDepth(nodes, depth = 0) {
if (!Array.isArray(nodes) || nodes.length === 0) return 0;
let maxChildDepth = 0;
for (const node of nodes) {
// 递归计算子树深度
const childDepth = setDepth(node.children);
node.depth = childDepth + 1; // 当前节点深度 = 子树最大深度 + 1
maxChildDepth = Math.max(maxChildDepth, node.depth);
}
return maxChildDepth;
}
function sortTree(nodes) {
if (!Array.isArray(nodes)) return;
// 主排序:depth 降序;次排序:children.length 降序
nodes.sort((a, b) => (b.depth || 0) - (a.depth || 0) || (b.children?.length || 0) - (a.children?.length || 0));
// 递归排序每个子树
for (const node of nodes) {
sortTree(node.children);
delete node.depth; // 清理临时 depth 字段,保持数据纯净
}
}
// ✅ 使用示例
const tree = [{
value: '1',
children: [
{
value: '1.1',
children: [{ value: '1.1.1', children: [] }]
},
{
value: '1.2',
children: [{
value: '1.2.1',
children: [
{ value: '1.2.1.1', children: [] },
{ value: '1.2.1.2', children: [] }
]
}]
},
{
value: '1.3',
children: [{
value: '1.3.1',
children: [{
value: '1.3.1.1',
children: [{ value: '1.3.1.1.1', children: [] }]
}]
}]
}
]
}];
setDepth(tree);
sortTree(tree);
console.log(JSON.stringify(tree, null, 2));
// 输出中,'1.3'(深度 4)排第一,'1.2'(深度 3)次之,'1.1'(深度 2)最后 —— 符合预期注意事项与最佳实践
- depth 定义一致性:本方案中 depth 表示「该节点向下可达的最大层数」(根节点自身计为第 1 层)。例如:{value:'x', children:[]} → depth = 1;{value:'y', children:[{children:[]}]} → depth = 2。
- 空 children 安全:代码显式检查 node.children?.length,兼容 children: undefined 或 null 场景。
- 原地排序 & 无副作用:sortTree() 直接修改原数组,且自动删除 depth,避免污染业务数据。
- 性能提示:时间复杂度为 O(N × D)(N 为总节点数,D 为最大深度),适用于中等规模树(≤ 10k 节点)。超大规模建议结合 Memoization 缓存深度值。
- 扩展建议:如需升序、或增加第三级排序(如按 value 字典序),只需调整 sort() 回调函数即可。
通过此方法,你将获得一个结构清晰、语义明确、可复用的树排序工具,轻松支撑动态菜单折叠、可视化层级渲染、AI 思维链排序等高级场景。










