Алгоритм поиска узла и его родителя в данных дерева

#javascript #algorithm #treeview

Вопрос:

Допустим, у меня есть объект Javascript, структурированный ниже :

 const data = [{  id: 1,  type: "ORGANIZATION",  children: [  {  id: 11,  type: 'ORGANIZATION',  children: [  {  id: 111,  type: 'DEPARTMENT',  children: [  {  id: 1111,  type: 'DEPARTMENT',  children: null // final child  }  ]  },  {  id: 112,  type: 'DEPARTMENT',  children: [  //more children  ]  }  ]  },  {  id: 12,  type: 'DEPARTMENT',  children: [  //more children  ]  }  ] }]  

В приведенной выше структуре ORGANIZATION узел может иметь список меньших ORGANIZATION узлов и DEPARTMENT узлов, в то время DEPARTMENT как узел может иметь список меньших DEPARTMENT . Я пытаюсь написать алгоритм, чтобы получить родительский узел любого узла и информацию о нем в дереве, следуя этим правилам:

  • Алгоритм вернет 2 объекта orgInfo и deptInfo .
  • Если узел является ORGANIZATION типом, вернитесь orgInfo с самой информацией и верните deptInfo значение null.
  • Если узел является DEPARTMENT типом, верните шкаф orgInfo и вернитесь deptInfo с самой информацией.

Например , если алгоритм ищет id:1111 узел, он вернет deptInfo тот, у которого id = 1111, а orgInfo у которого id = 11 (родительский шкаф)

У меня уже есть свой алгоритм на Javascript, но когда я пытаюсь поместить его в свое приложение React Native, он отображается медленно. Вот мой код:

 const itemSelector = createSelector( // using selector for Redux   [  state =gt; state.LookUpReducer.selectedItem,  state =gt; state.globalReducer.department_tree,    ],  (item, tree) =gt; {  let nodePath = [];  let orgId, deptId;  searchTree(tree, item.id, (item) =gt; nodePath = [...item]);  console.log(nodePath);  nodePath.reverse().some(item =gt; {//reverse the path to find the closet parent  if (item.type == 'ORGANIZATION') {  orgId = item.id  return true  }  return false  })  nodePath.some(item =gt; {  if (item.type == 'DEPARTMENT') {  deptId = item.id  return true  }  return false  })  console.log("OrgID: "   orgId   " DeptID:"   deptId);  return {  .....  }  } )  const searchTree = (tree, nodeId, callback, path = []) =gt; { //nodeId : the node to be search  tree.forEach(item =gt; {  path.push({  id: item.id,  type: item.type  });  if (item.id == nodeId) {  callback(path); // node founded  }  else {  if (item.children) searchTree(item.children, nodeId, callback, path)  }  path.pop();  }) }   

Я знаю, что мой алгоритм проходит через все узлы в дереве, и я все еще не знаю, как остановить его, когда он найдет узел. Кто-нибудь может помочь мне найти лучшее решение для моего алгоритма ?

Ответ №1:

Вы можете просто выполнить поиск по глубине, и когда цикл возвращается из внутренних циклов, если найден отдел, но не организация, вы можете просто указать первую организацию, которую он пересекает, поскольку она уже выполняется в обратном порядке.

 const data = [{  id: 1,  type: "ORGANIZATION",  children: [  {  id: 11,  type: 'ORGANIZATION',  children: [  {  id: 111,  type: 'DEPARTMENT',  children: [  {  id: 1111,  type: 'DEPARTMENT',  children: null // final child  }  ]  },  {  id: 112,  type: 'DEPARTMENT',  children: [  //more children  ]  }  ]  },  {  id: 12,  type: 'DEPARTMENT',  children: [  //more children  ]  }  ] }]   let org, dep;  let loop = (nodes, id) =gt; {  if (org) {  return; // when you have already fond the org  }    if(!nodes){  return; // incase the final child  }   nodes.forEach(node =gt; {  if (node.id === id) {  node.type === 'ORGANIZATION' ? org = node : dep = node; // if you find the org or dep no need to loop children  } else {  loop(node.children, id); // if not found go one level deeper.   if (!org amp;amp; dep amp;amp; node.type === 'ORGANIZATION') { // on returning from deeper level when you have found department but not an organization yet set it here  org = node;   }  }  });  }  loop(data, 111);  console.log('organization :',org); console.log('department :', dep);