树缩减算法
背景:今天有这么一个需求就是叶节点数量只有一个而且深度太深造成了用户反感,需要缩减深度。
最终目标:1’替换2,2’替换4,3’替换8
数据结构:父节点持有子节点的list,子节点持有父节点的id,不是父节点本身,这样是因为循环引用在转json时会造成麻烦。
public void shrinkTree() { //根节点有孩子 if (!nodes.isEmpty()) { final Iterator<KnowledgeInfo> iterator = nodes.iterator(); while (iterator.hasNext()) { final KnowledgeInfo self = iterator.next(); shrinkTree(this, self, self); } } } /** * @param lastRoot 最近的一个多孩子父节点 * @param remove 父节点到叶节点之间的一个节点 可能是叶节点本身,如果不是叶节点则可能是要删除的节点 * @param self 当前节点 */ private void shrinkTree(KnowledgeInfo lastRoot, KnowledgeInfo remove, KnowledgeInfo self) { if (self.nodes == null || self.nodes.isEmpty()) { return; } //有独生子 if (self.nodes.size() == 1) { final KnowledgeInfo knowledgeInfo = self.nodes.get(0); //独生子已经是最末端了 //和最近根下的祖宗节点交换 if (knowledgeInfo.isLeaf == 1) { final int index = lastRoot.nodes.indexOf(remove); knowledgeInfo.setParentId(lastRoot.getId()); knowledgeInfo.setDepth((byte) (lastRoot.getDepth() + 1)); lastRoot.nodes.set(index, knowledgeInfo); //不是独生子还有孩子 } else { shrinkTree(lastRoot, remove, knowledgeInfo); } //有多个孩子根节点切换 } else { final Iterator<KnowledgeInfo> iterator = self.nodes.iterator(); while (iterator.hasNext()) { final KnowledgeInfo next = iterator.next(); if (next.isLeaf == 0) { shrinkTree(self, next, next); } } } }