0

0

JavaScript 中从数组构建固定度数的随机分层树结构

聖光之護

聖光之護

发布时间:2026-01-30 11:18:14

|

301人浏览过

|

来源于php中文网

原创

JavaScript 中从数组构建固定度数的随机分层树结构

本文介绍如何将任意长度的字符串数组转换为满足“每节点恰好3个子节点”规则的分层树结构,确保层级填充严格按广度优先顺序进行,避免深度不均衡。

在 JavaScript 中构建符合特定分支因子(如三叉树)和严格层级填充规则的树结构,关键在于模拟广度优先索引分配,而非简单递归或随机打乱。题目要求:每个父节点必须有且仅有 3 个子节点;下一层的所有父节点(即当前层全部子节点)必须全部就位后,才开始为它们分配各自的子节点——这本质上是完全三叉树的层序展开,而非深度优先的任意嵌套。

但需注意:原始答案中的 generateTree 实现存在逻辑错误(如 tempIndex 计算不匹配层级关系、slice 起始位置越界、递归终止条件不严谨),无法正确生成示例输出,且未实现「随机打乱」这一核心需求。下面提供一个健壮、可读、符合题意的解决方案:

NatAgent
NatAgent

AI数据情报监测与分析平台

下载

✅ 正确思路:层序索引 + Fisher-Yates 随机化

  1. 先打乱原数组,确保“随机性”;
  2. 按层序(BFS)分配节点:第 0 层 1 个根?不,题目示例以 3 个顶层 parent 开始 → 实际是森林(3 棵子树),即第 0 层含 3 个独立根节点;
  3. 每层节点数为 3^level(level 从 0 开始):
      - level 0 → 3 个根(索引 0~2)
      - level 1 → 9 个节点(作为 level 0 各根的子节点,索引 3~11)
      - level 2 → 27 个节点(作为 level 1 各节点的子节点,索引 12~38)
      以此类推;
  4. 使用队列模拟 BFS 构建:将待填充子节点的父节点入队,逐个为其分配下一层连续的 3 个元素。

✅ 可运行实现

const x = [
  'apple', 'bus', 'banana', 'pen', 'pencil', 'earth', 'planet', 'flat',
  'house', 'dream', 'train', 'space', 'drink', 'cola'
];

// Fisher-Yates 洗牌,确保随机性
function shuffle(arr) {
  const a = [...arr];
  for (let i = a.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [a[i], a[j]] = [a[j], a[i]];
  }
  return a;
}

// 构建三叉森林:每节点严格 3 子,层序填充
function createTernaryForest(arr) {
  if (arr.length === 0) return [];

  const shuffled = shuffle(arr);
  const roots = []; // 第 0 层:3 个根节点
  const queue = []; // 存储 { node, childStartIndex },用于分配子节点

  // 初始化第 0 层:取前 3 个作为根
  const rootCount = Math.min(3, shuffled.length);
  for (let i = 0; i < rootCount; i++) {
    const node = { parent: shuffled[i], children: [] };
    roots.push(node);
    queue.push({ node, childStartIndex: 3 + i * 3 }); // level 1 起始索引:3,6,9...
  }

  // BFS 分配子节点
  while (queue.length > 0) {
    const { node, childStartIndex } = queue.shift();
    const remaining = shuffled.length - childStartIndex;

    // 本节点最多取 min(3, 剩余元素数) 个子节点
    const take = Math.min(3, remaining);
    for (let i = 0; i < take; i++) {
      const childValue = shuffled[childStartIndex + i];
      const childNode = { parent: childValue, children: [] };
      node.children.push(childNode);

      // 若还有下一层空间(即该 childNode 后面仍有足够元素供其分配 3 子),则入队
      const grandChildStart = childStartIndex + 3 * 3 + i * 3; // level 2 起始:3+9=12, then +0/+3/+6...
      if (grandChildStart < shuffled.length) {
        queue.push({ node: childNode, childStartIndex: grandChildStart });
      }
    }
  }

  return roots;
}

// 使用示例
console.log(JSON.stringify(createTernaryForest(x), null, 2));

⚠️ 注意事项

  • 数组长度非 3^n 时自动截断:末尾不足 3 个元素的父节点只分配实际可用子节点(如示例中 'planet'、'dream' 等无孙节点);
  • 不强制满树:题目未要求补全,因此不填充 null 或占位符,保持结构紧凑;
  • 时间复杂度 O(n),空间 O(n),适合千级节点规模;
  • 若需单根树(而非 3 根森林),只需将 rootCount = 1 并调整初始 childStartIndex = 1 即可。

此方案严格遵循“先填满上层所有父节点,再向下层推进”的约束,同时保证随机性与结构确定性统一,是生产环境中可靠的选择。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

236

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

458

2024.03.01

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

319

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

212

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1502

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

624

2023.11.24

java读取文件转成字符串的方法
java读取文件转成字符串的方法

Java8引入了新的文件I/O API,使用java.nio.file.Files类读取文件内容更加方便。对于较旧版本的Java,可以使用java.io.FileReader和java.io.BufferedReader来读取文件。在这些方法中,你需要将文件路径替换为你的实际文件路径,并且可能需要处理可能的IOException异常。想了解更多java的相关内容,可以阅读本专题下面的文章。

653

2024.03.22

php中定义字符串的方式
php中定义字符串的方式

php中定义字符串的方式:单引号;双引号;heredoc语法等等。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

609

2024.04.29

C++ 设计模式与软件架构
C++ 设计模式与软件架构

本专题深入讲解 C++ 中的常见设计模式与架构优化,包括单例模式、工厂模式、观察者模式、策略模式、命令模式等,结合实际案例展示如何在 C++ 项目中应用这些模式提升代码可维护性与扩展性。通过案例分析,帮助开发者掌握 如何运用设计模式构建高质量的软件架构,提升系统的灵活性与可扩展性。

7

2026.01.30

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 4.3万人学习

TypeScript 教程
TypeScript 教程

共19课时 | 2.6万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 3.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号