javascript 对含有parent_id的数组进行拓扑排序,然后生成树状结构

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了javascript 对含有parent_id的数组进行拓扑排序,然后生成树状结构相关的知识,希望对你有一定的参考价值。

const _ = require("lodash");
// 按扭ID(整型,不可重复),按扭名称(字符串),父ID(按扭之间的关系,可为空)
// 100,桌面,0
// 101,开启桌面整理,100
// 102,退出桌面整理,100
// 103,一键桌面整理,100
const file = [["按扭ID(整型,不可重复)", "按扭名称(字符串)", "父ID(按扭之间的关系,可为空)"], ["100", "桌面", "0"], ["101", "开启桌面整理", "100"], ["102", "退出桌面整理", "100"], ["103", "一键桌面整理", "100"], ["104", "新建分区", "100"], ["105", "新建分区-桌面右键", "104"], ["106", "新建分区-分区右键", "104"], ["107", "新建分区-标题栏", "104"], ["108", "解散分区", "100"], ["109", "解散分区-分区右键", "108"], ["110", "解散分区-菜单面板", "108"], ["111", "解散分区-标题栏", "108"], ["112", "锁定分区", "100"], ["113", "锁定分区-菜单面板", "112"], ["114", "锁定分区-标题栏", "112"], ["115", "重命名", "100"], ["116", "查看方式", "100"], ["117", "查看方式-分区右键", "116"], ["118", "大图标", "117"], ["119", "中等图标", "117"], ["120", "小图标", "117"], ["121", "查看方式-菜单面板", "116"], ["122", "大图标", "121"], ["123", "中等图标", "121"], ["124", "小图标", "121"], ["125", "查看方式-底部栏", "116"], ["126", "切换至图标模式", "125"], ["127", "切换至列表模式", "125"], ["128", "查看方式-桌面右键", "116"], ["129", "大图标", "128"], ["130", "中等图标", "128"], ["131", "小图标", "128"], ["132", "自动排列", "128"], ["133", "开启自动排列", "132"], ["134", "关闭自动排列", "132"], ["135", "双击隐藏桌面图标", "128"], ["136", "开启双击隐藏", "135"], ["137", "关闭双击隐藏", "135"], ["138", "显示桌面图标和格子", "128"], ["139", "显示桌面图标和格子", "138"], ["140", "不显示桌面图标和格子", "138"], ["141", "快捷方式小箭头", "128"], ["142", "显示小箭头", "141"], ["143", "不显示小箭头", "141"], ["144", "排序方式", "100"], ["145", "排序方式-分区右键", "144"], ["146", "排序-名称", "145"], ["147", "排序-项目类型", "145"], ["148", "排序-大小", "145"], ["149", "排序-修改时间", "145"], ["150", "排序方式-菜单面板", "144"], ["151", "排序-名称", "150"], ["152", "排序-项目类型", "150"], ["153", "排序-大小", "150"], ["154", "排序-修改时间", "150"], ["155", "排序方式-底部栏", "144"], ["156", "排序-名称", "155"], ["157", "排序-项目类型", "155"], ["158", "排序-大小", "155"], ["159", "排序-修改时间", "155"], ["160", "置顶", "100"], ["161", "取消置顶", "100"], ["162", "移入回收站", "100"], [], [], ["200", "主面板", "0"], ["201", "新建标签", "200"], ["202", "新建标签-标签栏空白处右键", "201"], ["203", "新建标签-标签栏底部按钮", "201"], ["204", "新建标签-空白标签", "201"], ["205", "新建标签-桌面分区", "201"], ["206", "删除标签", "200"], ["207", "删除标签-标签处右键", "206"], ["208", "删除标签-标签内空白处右键", "206"], ["209", "删除标签-桌面分区", "206"], ["210", "删除标签-普通", "206"], ["211", "贴边隐藏", "200"], ["212", "贴边隐藏-顶部右侧", "211"], ["213", "贴边隐藏-顶部左侧", "211"], ["214", "贴边隐藏-顶部中间", "211"], ["215", "贴边隐藏-左侧上边", "211"], ["216", "贴边隐藏-左侧中间", "211"], ["217", "贴边隐藏-左侧下边", "211"], ["218", "贴边隐藏-右侧上边", "211"], ["219", "贴边隐藏-右侧中间", "211"], ["220", "贴边隐藏-右侧下边", "211"], ["221", "查看方式", "200"], ["222", "查看方式-标签内空白处右键", "221"], ["223", "大图标", "222"], ["224", "中等图标", "222"], ["225", "小图标", "222"], ["226", "查看方式-标签处右键", "221"], ["227", "大图标", "226"], ["228", "中等图标", "226"], ["229", "小图标", "226"], ["230", "查看方式-底部栏", "221"], ["231", "大图标", "230"], ["232", "中等图标", "230"], ["233", "小图标", "230"], ["234", "排序方式", "200"], ["235", "排序方式-标签内空白处右键", "234"], ["236", "排序-名称", "235"], ["237", "排序-项目类型", "235"], ["238", "排序-大小", "235"], ["239", "排序-修改时间", "235"], ["240", "排序方式-标签处右键", "234"], ["241", "排序-名称", "240"], ["242", "排序-项目类型", "240"], ["243", "排序-大小", "240"], ["244", "排序-修改时间", "240"], ["245", "排序方式-底部栏", "234"], ["246", "排序-名称", "245"], ["247", "排序-项目类型", "245"], ["248", "排序-大小", "245"], ["249", "排序-修改时间", "245"], ["250", "窗口", "200"], ["251", "放大", "250"], ["252", "缩小", "250"], ["253", "文件", "200"], ["254", "打开", "253"], ["255", "删除", "253"], ["256", "打开文件所在位置", "253"], [], [], ["300", "设置", "0"], ["301", "基础设置", "300"], ["302", "开机时整理桌面", "301"], ["303", "开启", "302"], ["304", "关闭", "302"], ["305", "启动时显示主面板", "301"], ["306", "开启", "305"], ["307", "关闭", "305"], ["308", "桌面", "300"], ["309", "分区设置", "308"], ["310", "收起后,鼠标移到标题自动展开", "309"], ["311", "开启", "310"], ["312", "关闭", "310"], ["313", "快捷操作", "308"], ["314", "双击桌面空白处,隐藏桌面图标", "313"], ["315", "开启", "314"], ["316", "关闭", "314"], ["317", "提醒设置", "308"], ["318", "双击桌面空白处隐藏桌面图标时提醒", "317"], ["319", "开启", "318"], ["320", "关闭", "318"], ["321", "主面板", "300"], ["322", "标签设置", "321"], ["323", "标签切换", "322"], ["324", "鼠标悬停切换标签", "323"], ["325", "鼠标单击切换标签", "323"], ["326", "操作设置", "321"], ["327", "打开交互", "326"], ["328", "鼠标单击打开文件或应用", "327"], ["329", "鼠标双击打开文件或应用", "327"], ["330", "窗口显示", "321"], ["331", "停靠在桌面边缘时自动吸附隐藏", "330"], ["332", "开启", "331"], ["333", "关闭", "331"], ["334", "始终保持在其他窗口前端", "330"], ["335", "开启", "334"], ["336", "关闭", "334"], ["337", "关于", "300"], ["338", "点击检查更新", "337"], ["339", "点击官网", "337"], [], [], [], ["400", "托盘", "0"], ["401", "左键单击", "400"], ["402", "右键单击", "400"], ["403", "主面板", "402"], ["404", "设置", "402"], ["405", "退出", "402"], ["406", "退出", "402"]]
const data = file.map(tuple=>({
  self_id:tuple[0],
  button_name:tuple[1],
  parent_id:tuple[2],
}))

function QueueTree(data){
  let root = {self_id: '0', children:[]};
  let nodes = [root];
  
  let queue = _.clone(data);
  while(!_.isEmpty(queue)){
    const top = queue.shift();
    const {self_id, button_name, parent_id} = top;
    
    let node = {
      self_id,
      button_name,
      parent_id,
      children: []
    }
  
    let parent = _.find(nodes, {self_id: parent_id});
    if (parent) {
      parent.children.push(node)
      nodes.push(node)
    } else {
      nodes.push(node)
    }
  }
  console.log(root)
  console.log(JSON.stringify(root))
}

// 拓扑排序: DFS 深度优先搜索完成之后。按照完成时间从大到小的顺序对结点排序。
function TOPOLOGICAL_SORT(data){
  let graph = DFS(data)
  
  // 按照完成时间从大到小的顺序对结点排序。
  const sortedGraph  = _.sortBy(graph, 'f_time')
  console.log("拓扑排序", sortedGraph.map(n => [n.f_time, n.self_id, n.parent_id]))
    
  return sortedGraph;
}

let globalTime = 1;
// 深度优先搜索
function DFS(data){
  let graph = data.map(node =>({
    ...node,
    color: "white",
    // children: []
  }))
  _.forEach(graph, (node)=>{
    DFS_VISIT(graph, node)
  })

  return graph;
  // console.log(graph)
  // console.log(JSON.stringify(graph))
}
// 深度优先搜索
function DFS_VISIT(graph, node){
  globalTime += 1
  node.d_time = globalTime
  node.color = 'gray'
  
  // 找到所有当前节点的孩子
  let children = _.filter(graph, {parent_id: node.self_id})
  _.forEach(children, (child)=>{
    if (child && child.color == 'white'){
      // node.children.push(child)
      DFS_VISIT(graph, child)
    }
  })
  node.color = 'black'
  globalTime += 1
  node.f_time = globalTime
}
// TOPOLOGICAL_SORT(data)
// DFS(data);
let sortedQueue = TOPOLOGICAL_SORT(data);
QueueTree(sortedQueue)



    let parent = _.find(nodes, {self_id: parent_id});
    if (parent) {
      parent.children.push(node)
      nodes.push(node)
    } else {
      nodes.push(node)
    }
  }
  console.log(root)
  console.log(JSON.stringify(root))
}

// 拓扑排序: DFS 深度优先搜索完成之后。按照完成时间从大到小的顺序对结点排序。
function TOPOLOGICAL_SORT(data){
  let graph = DFS(data)
  
  // 按照完成时间从大到小的顺序对结点排序。
  const sortedGraph  = _.sortBy(graph, 'f_time')
  console.log("拓扑排序", sortedGraph.map(n => [n.f_time, n.self_id, n.parent_id]))
    
  return sortedGraph;
}

let globalTime = 1;
// 深度优先搜索
function DFS(data){
  let graph = data.map(node =>({
    ...node,
    color: "white",
    // children: []
  }))
  _.forEach(graph, (node)=>{
    DFS_VISIT(graph, node)
  })

  return graph;
  // console.log(graph)
  // console.log(JSON.stringify(graph))
}
// 深度优先搜索
function DFS_VISIT(graph, node){
  globalTime += 1
  node.d_time = globalTime
  node.color = 'gray'
  
  // 找到所有当前节点的孩子
  let children = _.filter(graph, {parent_id: node.self_id})
  _.forEach(children, (child)=>{
    if (child && child.color == 'white'){
      // node.children.push(child)
      DFS_VISIT(graph, child)
    }
  })
  node.color = 'black'
  globalTime += 1
  node.f_time = globalTime
}
// TOPOLOGICAL_SORT(data)
// DFS(data);
let sortedQueue = TOPOLOGICAL_SORT(data);
QueueTree(sortedQueue)


以上是关于javascript 对含有parent_id的数组进行拓扑排序,然后生成树状结构的主要内容,如果未能解决你的问题,请参考以下文章

找出数组中差值为k去重后的数对

含有n个元素的整型数组,将这个n个元素重新组合,求出最小的数,如{321,3,32},最小的数为321323

为啥 外链javascript脚本,不能含有script标签

挑剔的小杜

2021-08-27:正常的里程表会依次显示自然数表示里程,吉祥的里程表会忽略含有4的数字而跳到下一个完全不含有4的数。正常:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15(代

用c语言编程实现输出100以内的所有是3的倍数,或者含有3的正整数。要求输出时所有的数都以逗号隔开