树型结构的数据怎么匹配分支

img

问题描述:

仔细看上图数据结构会发现value和parent是有关联的,这种关联非常类似于树型数据,那问题来了,这种数据是可以有n层数据的,要怎么查找并对树型数据进行处理就成了1大问题,我想实现只需要通过某个value值就可以获取到往上的每一个分支数据并可以进行处理,比如对show属性赋值什么的,往上查找有n个分支的可能(n个的意思是往上不知道有多少层),然后往下只需要找1个分支(只需要通
过value匹配一下parent就可以)。for循环应该没办法处理树型数据,树型数据应该要使用递归算法来处理,希望能给一个正解。

结构描述:

value -- 类似于ID
parent -- 类似于父级ID

思路:

1.要想通过某个value来找到上级,应该是先匹配当前value的对象,然后通过下标或对象拿到当前对象的parent,最后再用parent去匹配value就可以匹配到父级了。(问题在这里,这个思路只能匹配到一个分支,但是我想匹配到往上的n个分支)
2.要想通过某个value来找到子级,应该是直接用value匹配parent,这样就可以找到所有子级了。(这个思路只能匹配到一个分支)

找父节点一般只有一条路径吧,为什么会出现多个呢?一个节点一般只有一个父节点,难道还要找父节点兄弟节点的子节点?

找指定节点所有子节点简单,将这个节点的value和遍历到的子节点的value全部压入数组,是否子节点遍历到的节点的parent是否在数组即可。


    let list = [
        {name:'全部分类', value: null, parent: null },
        { name: '视频', value: '682395', parent: null },
        { name: '音频', value: '971824', parent: null },
        { name: '流量', value: '891628', parent: null },
        { name: '编辑', value: '276312', parent: null },
        { name: '原创', value: '785312', parent: '682395' },
        { name: '改编', value: '981726', parent: '682395' },
        { name: '美食', value: '217241', parent: '785312' },
        { name: '科技', value: '783102', parent: '785312' },
        { name: '动画', value: '412842', parent: '981726' },
    ]
    function getParentNodes(value,list) {//只有一条,没搞清楚找父节点会有多个分支
        var node = list.find(i => i.value == value);
        if (node) {//找到节点
            var pNodes = [];//如果需要放入查找的节点这里改为var pNodes = [node];
            while (node = list.find(i => i.value == node.parent)) {
                pNodes.unshift(node);//将父节点前插
                if (node.value === null) break;//找到顶级节点退出
            }

            return pNodes;
        }

        return null;//找不到需要查找的value返回null,注意判断getParentNodes函数返回值
    }


    function visitChildren(value, list) {
        var index = list.findIndex(i => i.value == value);
        if (index != -1) {//找到节点
            var pids = [list[index].value];//父节点集合
            for (var i = index + 1; i < list.length; i++) {
                if (pids.includes(list[i].parent)) {
                    console.log(list[i]);//子节点
                    pids.push(list[i].value);//加入父id
                }
            }
        }
    }

你这是需要根据value,parent 关系把生成树形结构的数据吧?用递归实现的,试试看。

function initTreeData(treeList) {
      let treeData = {};
      function query(list, i) {
        list.forEach((v) => {
          if (v.value === i.parent) v.children = [...(v?.children ?? []), i];
          if (list?.children) query(list.children, i);
        });
      }
      treeList.forEach((i) => {
        if (!i.value && !i.parent) {
          treeData = i;
          treeData.children = treeList.filter(
            (item) => item.value && !item.parent
          );
          return;
        }
        if (i?.value && i?.parent) query(treeList, i);
      });
      return treeData;
    },

const data = [
    { name: '全部分类', value: null, parent: null },
    { name: '视频', value: '682395', parent: null },
    { name: '音频', value: '971824', parent: null },
    { name: '流量', value: '891628', parent: null },
    { name: '编辑', value: '276312', parent: null },
    { name: '原创', value: '785312', parent: '682395' },
    { name: '改编', value: '981726', parent: '682395' },
    { name: '美食', value: '217241', parent: '785312' },
    { name: '科技', value: '783102', parent: '785312' },
    { name: '动画', value: '412842', parent: '981726' },
]
const findParent = (child) => {
    const target = data.find(item => item.value == child.parent)
    if(target != child)
        return target;
    else
        return null;
}
data.forEach(item => {
    const parent = findParent(item)
    if(parent) {
        if(!parent.children)
            parent.children = [];
        parent.children.push(item);
        //使用对象来代替原来的字符串,如果不喜欢可以使用其它字段名称
        item.parent = parent;
    }
});
console.log(data);

//查找某个指定值的所有父级并设置字段值
let result = data.find(item => item.value == "981726")
let target = result
do {
    target.show = true
    target = target.parent;
} while(target != null)
//对于子级最后使用父级的show来判断是否显示,parent.show || child.show,不建议直接设置,如果硬要设置
const setChildrenProperties = (parent, setter) => {
    parent.children && parent.children.forEach(child => {
        setter(child);
        setChildrenProperties(child, setter);
    })
}
setChildrenProperties(result, child => child.show = true);

```

如果要查找某个value的父级,可以使用递归函数,每次通过当前value的对象的parent去匹配数据中的value,直到没有对象的parent为止。对于每一层递归,都可以记录父级的信息,最终返回往上的n个分支的信息。

如果要查找某个value的子级,可以遍历整个数据集,匹配所有parent与当前value相同的对象,最终得到所有子级的信息。

可以采用队列加递归的方式处理,这个肯定不能简单循环解决。

递归算法是可以递归往上寻找父级,也可以递归往下寻找子级的。

基于以上思路,我们可以写一个递归函数,每次把当前的value当做参数传递给递归函数,递归函数内部先判断当前的value是否满足条件,如果满足就进行处理,否则递归查找它的父级。如果父级不存在,则递归结束。

对于寻找子级的情况,我们可以把当前的value当做参数传递给递归函数,递归函数内部先判断当前的value是否满足条件,如果满足就进行处理,否则递归查找它的子级。如果子级不存在,则递归结束

const data = [  {value: 1, parent: 0},  {value: 2, parent: 1},  {value: 3, parent: 1},  {value: 4, parent: 2},  {value: 5, parent: 3},];

const findParent = (value) => {
  let result = [];
  for (let i = 0; i < data.length; i++) {
    if (data[i].value === value) {
      let parent = data[i].parent;
      result.push(data[i]);
      while (parent !== 0) {
        for (let j = 0; j < data.length; j++) {
          if (data[j].value === parent) {
            result.push(data[j]);
            parent = data[j].parent;
            break;
          }
        }
      }
      break;
    }
  }
  return result.reverse();
};

const findChildren = (value) => {
  let result = [];
  for (let i = 0; i < data.length; i++) {
    if (data[i].parent === value) {
      result.push(data[i]);
    }
  }
  return result;
};

console.log(findParent(4));
// Output: [ { value: 4, parent: 2 }, { value: 2, parent: 1 }, { value: 1, parent: 0 } ]

console.log(findChildren(1));
// Output: [ { value: 2, parent: 1 }, { value: 3, parent: 1 } ]


public class TreeNode {
    int value;
    int parent;
    // 其他属性
    // ...
}

public class Tree {
    List<TreeNode> nodes = new ArrayList<>();

    // 查询某个节点的所有父级节点
    public List<TreeNode> getParents(int value) {
        TreeNode node = findNode(value);
        List<TreeNode> parents = new ArrayList<>();
        while (node.parent != -1) {
            node = findNode(node.parent);
            parents.add(node);
        }
        return parents;
    }

    // 查询某个节点的所有子级节点
    public List<TreeNode> getChildren(int value) {
        List<TreeNode> children = new ArrayList<>();
        for (TreeNode node : nodes) {
            if (node.parent == value) {
                children.add(node);
            }
        }
        return children;
    }

    // 查询节点
    private TreeNode findNode(int value) {
        for (TreeNode node : nodes) {
            if (node.value == value) {
                return node;
            }
        }
        return null;
    }
}