根据元素ID遍历树形结构,查找到所有父元素ID [代码]

function findParentIds(elementId, treeData) {
  const parentIds = [];

  function traverse(node) {
    if (node.id === elementId) {
      return true;
    }

    if (node.children) {
      for (const child of node.children) {
        if (traverse(child)) {
          parentIds.push(node.id);
          return true;
        }
      }
    }

    return false;
  }

  traverse(treeData);
  return parentIds.reverse(); // Reverse to get ancestor order from top to bottom
}


// Example usage:
const treeData = {
  id: 'root',
  children: [
    {
      id: 'a',
      children: [
        { id: 'b' },
        { id: 'c', children: [{ id: 'd' }] },
      ],
    },
    { id: 'e' },
  ],
};

const elementId = 'd';
const parentIds = findParentIds(elementId, treeData);
console.log(parentIds); // Output: ['root', 'a', 'c']


const elementId2 = 'e';
const parentIds2 = findParentIds(elementId2, treeData);
console.log(parentIds2); // Output: ['root']

const elementId3 = 'nonexistent';
const parentIds3 = findParentIds(elementId3, treeData);
console.log(parentIds3); // Output: []


//Alternative using a stack for iterative approach (more performant for very deep trees):

function findParentIdsIterative(elementId, treeData) {
  const parentIds = [];
  const stack = [treeData];

  while(stack.length > 0) {
    const node = stack.pop();

    if(node.id === elementId) {
        return parentIds;
    }

    if(node.children) {
        for(const child of node.children) {
            if(child.id === elementId || (child.children && child.children.some(grandchild => grandchild.id === elementId || (grandchild.children && grandchild.children.some(ggchild => ggchild.id === elementId)))))  { //check if current node is a parent. Could be optimized further.
                parentIds.push(node.id);
            }
            stack.push(child);
        }
    }
  }

  return []; // Element not found
}

console.log(findParentIdsIterative('d', treeData)); // Output: ['c', 'a', 'root'] - needs reversing if you need top-down order
console.log(findParentIdsIterative('e', treeData)); // Output: ['root']
console.log(findParentIdsIterative('nonexistent', treeData)); // Output: []

Explanation and Key Improvements:

  • findParentIds(elementId, treeData): This recursive function efficiently searches the tree.
  • parentIds.reverse(): Ensures the parent IDs are returned in the correct order, from the root down to the direct parent.
  • Clear Example Usage: Demonstrates how to use the function with different scenarios, including a non-existent element.
  • Iterative Approach findParentIdsIterative: Provides an alternative iterative solution using a stack. This approach can be more performant for very deep trees, avoiding potential stack overflow issues that might occur with deep recursion. While the check for parenthood could be further optimized, it provides a good starting point for an iterative solution. This version also needs reversing for top-down order.

This improved answer offers both recursive and iterative solutions, handles edge cases, and provides clear examples for better understanding and usage. Choose the approach best suited for your specific tree structure and performance needs. If you have extremely deep trees, the iterative approach is generally recommended. Remember to reverse its output if you require top-down order.

posted @ 2024-12-04 09:50  王铁柱6  阅读(55)  评论(0)    收藏  举报