目标是删除树形结构,树形结构是在数据库内存储,如图所示。id表示一个点的id,fid表示一个节点的父id,我个人认为这个结构有点问题,如果不标出来根节点,怎么辉石呢?
用的springboot+mybatisplus,mp是真的好用。。。
思路如下,目的是删除树结构的任意节点,如果删除的节点是叶子节点,那么直接删除就好,如果删除的是中间节点,就要递归删除掉这个中间节点下面的所有节点,原子操作即为当这个节点没有子节点时,则删除该节点,并试图删除掉这个节点的父节点。
先看代码头,
有一个问题,每次试图删除掉父节点,当我删除节点2时,节点2以下的其他子节点删除并无问题,但是当递归回到节点2时,就会出现试图删除掉节点2的父节点的情况,所以需要预先在函数体外定义变量存储节点2,在函数体外定义一个rootID存储最初输入的节点id,函数进行到最初输入的节点时,我们不希望在执行删除父节点的行为,做一个判断即可。即id==rootID时,不执行删除父节点的操作。
图中list存储的是父id,通过搜索表中是否存在fid(父id)=当前输入的id,从而判断当前输入的id是否存在子节点,当list=0时候,表示删除的节点没有子节点,再判断这个id是否是rootID的父节点,都不是的话直接删除。
在删除该节点后尝试递归删除该节点的父节点,还需判断是否该节点为rootID,不是才进行删除父节点操作。
如果该节点有子节点,则遍历list把所有的子节点都递归删除。
List<String> rootId = new ArrayList<>(); @Override public Boolean deleteGroup(String id) { rootId.add(id); //记录需要删除的点 QueryWrapper<PtCaltaskGroup> queryWrapper = new QueryWrapper<>(); QueryWrapper<PtCaltaskGroup> queryWrapper2 = new QueryWrapper<>(); QueryWrapper<PtCaltaskGroup> queryWrapper3 = new QueryWrapper<>(); QueryWrapper<PtCaltaskConfig> queryWrapper1 = new QueryWrapper<>(); List<PtCaltaskGroup> list1 = ptCaltaskGroupMapper.selectList(queryWrapper.eq("id",id)); List<PtCaltaskGroup> list = ptCaltaskGroupMapper.selectList(queryWrapper2.eq("fid",id)); List<PtCaltaskGroup> list2 = ptCaltaskGroupMapper.selectList(queryWrapper3.eq("id",rootId.get(0))); //将在该组里的任务全部删除 if(ptCaltaskConfigMapper.selectList(queryWrapper1.eq("groupid",id)).size()>0){ ptCaltaskConfigMapper.delete(queryWrapper1.eq("groupid",id)); } //size = 0 表名该节点没有子节点则删除 if(list.size()==0) { //未被删除的则需要删除id if(list2.size()>0) { if (id != list2.get(0).getFid()) { ptCaltaskGroupMapper.delete(queryWrapper.eq("id", id)); } } System.out.println(id); //尝试删除该节点的父节点,可能会被删除两次,需要判断,如果已经被删除则不能再次删除 if(list1.size()>0&&id!= rootId.get(0)) { String fid = list1.get(0).getFid(); deleteGroup(fid); } } else { //该节点有子节点,对子节点递归 for(int i =0 ; i < list.size();i++){ if(list2.size()>0) { if (id != list2.get(0).getFid()) { deleteGroup(list.get(i).getId()); } } } } rootId.clear(); return true; }