本质上就是对树状结构数据的一个递归遍历+数据比对+数据筛选(保留)
难点在于非扁平化的树结构在筛选时保留时的取舍,这里的关键是,只要节点存在keyword,那么根节点到当前节点的树结构就必须保留,所以对节点的操作必须放在遍历后
这里有必要回顾一下数据结构中的二叉树的遍历方式,开发中最常用还是前序遍历(根左右),遍历的目的是访问树结构的每一个节点(且只访问一次),对节点进行一些操作(新增,修改,删除)
前序遍历可以满足大多数开发场景。但如果涉及到树结构的断层拼接、树结构的模糊查询等等根据条件多层级保留的场景,前序遍历就很无力。因为操作树结构是children渐渐往外发散的,从前往后遍历操作,会丢失掉父层级
后续遍历每个节点,遍历完之后再 左右根 顺序做判断筛选。遍历返回值为临时数组,存放包含keyword的树节点
叶子节点终止遍历(children.length==0)
当前节点两种情况:
这里用JS实现一下这个过程,其他强类型语言只需要加上变量的类型限制即可,方法思路一致
- /**
- * 根据关键字检索专题
- * @param String searchValue 输入的关键字
- * @param treeNode searchTopicCatalogs 待搜索的树结构
- * @returns {*}treeNode res
- * @private
- * 递归查询检索
- */
- const recursionHandler = (searchValue, searchTopicCatalogs) => {
- let tempSearchArr = [];
- searchTopicCatalogs.forEach((treeNode) => {
- if (treeNode.children && treeNode.children.length > 0) {
- // 后序遍历
- let tempArr = this.recursionHandler(searchValue, treeNode.children);
- // 当前树节点的子节点存在匹配字符,直接纳入数组
- if (tempArr.length > 0) {
- tempSearchArr.push(treeNode);
- }
- //当前树节点存在匹配字符
- else {
- if (treeNode.title.indexOf(searchValue) >= 0) {
- tempSearchArr.push(treeNode);
- }
- }
- }
- // 叶子节点
- else {
- // 当前树节点存在匹配字符
- if (treeNode.title.indexOf(searchValue) >= 0) {
- tempSearchArr.push(treeNode);
- }
- }
- });
- return tempSearchArr;
- }