初次涉及左右值算法(树结构)
1.无限极新增节点
int maxChildRgtVal = orgParent.getRgtVal() - 1; //真理 if (orgParent.getChildNodeCount() != 0) {//如果有子节点,获取子节点最大的右值 org.setLftVal(maxChildRgtVal + 1); org.setRgtVal(maxChildRgtVal + 2); } else { org.setLftVal(orgParent.getLftVal() + 1); org.setRgtVal(orgParent.getLftVal() + 2); } //更新子节点数 orgDAO.update(orgParent.setChildNodeCount(orgParent.getChildNodeCount() + 1)); //修改右值 orgDAO.updateCus(new CusPara() .setStrWhere(String.format(" and rgt_val > %s ", maxChildRgtVal)) .setStrSet(String.format(" rgt_val=rgt_val + %s", OrgEnum.INIT_RIGHT))); //修改左值 orgDAO.updateCus(new CusPara() .setStrWhere(String.format(" and lft_val > %s ", maxChildRgtVal)) .setStrSet(String.format("lft_val=lft_val + %s", OrgEnum.INIT_RIGHT)));
2.无限极删除节点
//连同子节点一起软删除(修改状态) cusPara.setStrWhere( String.format(" and lft_val >= %s and rgt_val <= %s ", org.getLftVal(), org.getRgtVal())) .setStrSet("status = " + DBStatus.DISABLED); int rs = orgDAO.updateCus(cusPara); //左右值差值 int lftRgtDiff = param.getRgtVal() - param.getLftVal() + 1; //重新修改左右值 orgDAO.updateCus(new CusPara() .setStrWhere(String.format(" and rgt_val >= %s ", org.getLftVal())) .setStrSet(String.format("rgt_val = rgt_val - %s", lftRgtDiff))); orgDAO.updateCus(new CusPara() .setStrWhere(String.format(" and lft_val >= %s ", org.getLftVal())) .setStrSet(String.format("lft_val = lft_val - %s", lftRgtDiff)));
3.无限极随意移动节点左右值算法,请各位大神指正,谢谢
public void changeOrgParent(Org org){ //当前节点的旧左右值 Org old_org=orgDAO.getOneById(org.getId()); int old_rgt=old_org.getRgtVal(); int old_lft=old_org.getLftVal(); if(org.getParentId().longValue()==old_org.getParentId().longValue()){ orgDAO.update(org); }else { //获取当前节点的子孙节点 List<Org> sub_list=orgDAO.getCusAll(new CusPara().setStrWhere(String.format(" and lft_val> %s and rgt_val< %s " , old_lft,old_rgt))); //获取新父节点 Org pOrg=orgDAO.getOneById(org.getParentId()); //新父节点左右值 int p_rgt=pOrg.getRgtVal(); int p_lft=pOrg.getLftVal(); //计算当前节点的新左右值 int new_lft=p_rgt; int new_rgt=old_rgt-(old_lft-new_lft); //计算偏移量 int move=new_rgt-old_rgt; //给当前节点赋新的左右值 org.setRgtVal(new_rgt); org.setLftVal(new_lft); //检查新的父节点是否是当前节点的子孙节点 boolean is_sub= sub_list.stream().anyMatch(u ->u.getId().toString().equals(org.getParentId().toString())); if(is_sub){ //获取当前节点原来的父节点 if(null!=old_org&&null!=old_org.getParentId()){ Org old_parent_org=orgDAO.getOneById(old_org.getParentId()); //检查旧的父节点的父节点的父节点是否是为 1 的顶级节点,是就不能移动当前节点 Org p_p_org=orgDAO.getOneById(old_parent_org.getParentId()); if(null!=p_p_org&&p_p_org.getParentId()>1){ //新的偏移量算法 int new_move=new_rgt-new_lft+1; //所有的右值大于当前节点的旧右值(移动节点的原来右值),左右值加上偏移量 int other_l_num=orgDAO.updateCus(new CusPara() .setStrSet(String.format(" rgt_val=rgt_val + %s ,lft_val=lft_val + %s" ,new_move,new_move)) .setStrWhere(String.format(" and rgt_val> %s " , old_rgt))); // 所有的左值大于当前节点的旧右值,左都加上偏移量 CusPara cusPara=new CusPara(); cusPara.setStrSet(String.format(" lft_val=lft_val + %s ",new_move)); cusPara.setStrWhere(String.format(" and lft_val>%s " , old_rgt)); int other_num=orgDAO.updateCus(cusPara); //更新当前节点的新父节点 orgDAO.updateCus(new CusPara().setStrSet(String.format(" lft_val= + %s,rgt_val=rgt_val + %s,parent_id= %s",old_lft,new_move,old_org.getParentId())) .setStrWhere(String.format(" and id=%s " , pOrg.getId()))); //更新当前节点 org.setLftVal(new_lft); org.setRgtVal(new_rgt); orgDAO.update(org); //提取左值大于新父节点的原右值 List<Org> list_r=sub_list.stream() .filter(u->u.getLftVal()>p_rgt&&!(u.getId().equals(org.getParentId()))) .collect(Collectors.toList()); if(list_r.size()>0){ //更新子孙节点,左右值都加上偏移量-1 String ids=StringUtils.join(list_r.stream().map(Org::getId).collect(Collectors.toList()),","); orgDAO.updateCus(new CusPara() .setStrSet(String.format(" lft_val=lft_val + %s , rgt_val= rgt_val+ %s " , move-1,move-1)) .setStrWhere(String.format(" and id in(%s)" ,ids))); } //提取右值小于新父节点的原左值 List<Org> list_l=sub_list.stream() .filter(u->u.getLftVal()<p_lft&&!(u.getId().equals(org.getParentId()))) .collect(Collectors.toList()); if(list_l.size()>0){ //更新子孙节点,左右值都加上偏移量-1 String ids=StringUtils.join(list_l.stream().map(Org::getId).collect(Collectors.toList()),","); orgDAO.updateCus(new CusPara() .setStrSet(String.format(" lft_val=lft_val + %s , rgt_val= rgt_val+ %s " , move-1,move-1)) .setStrWhere(String.format(" and id in(%s)" ,ids))); } } } }else { //新节点的右值小于当前节点的右值 if(new_rgt<old_rgt){ //更新当前节点 int num=orgDAO.update(org); if(num>0){ if(sub_list.size()>0){ //更新当前节点原来子孙节点 int sub_num= orgDAO.updateCus(new CusPara() .setStrSet(String.format(" lft_val=lft_val + %s , rgt_val=rgt_val + %s " , move,move)) .setStrWhere(String.format(" and lft_val> %s and rgt_val< %s " , old_lft,old_rgt))); if(sub_num>0){ //重算偏移量 move=new_rgt-new_lft+1; //所有的左值小于新父节点的左值,右值大于新父节点的右值,也就是整条父节点的右值加上偏移量 int other_l_num=orgDAO.updateCus(new CusPara() .setStrSet(String.format(" rgt_val=rgt_val + %s " ,move)) .setStrWhere(String.format(" and rgt_val>= %s and lft_val<= %s" , p_rgt,p_lft))); List<Long> stringList=sub_list.stream().map(Org::getId).collect(Collectors.toList()); String ids=StringUtils.join(stringList,","); //所有的左值大于新父节点的右值不包括子孙节点,左右值都加上偏移量 CusPara cusPara=new CusPara(); cusPara.setStrSet(String.format(" lft_val=lft_val + %s , rgt_val= rgt_val+ %s " , move,move)); cusPara.setStrWhere(String.format(" and lft_val>%s and id not in(%s)" , p_rgt,ids)); int other_num=orgDAO.updateCus(cusPara); }else { throw new RuntimeException("1014更新子孙节点失败!"); } }else { //重算偏移量 move=new_rgt-new_lft+1; //所有的左值小于新父节点的左值,右值大于新父节点的右值,也就是整条父节点的右值加上偏移量 int other_l_num=orgDAO.updateCus(new CusPara() .setStrSet(String.format(" rgt_val=rgt_val + %s " ,move)) .setStrWhere(String.format(" and rgt_val >= %s and lft_val<= %s" , p_rgt,p_lft))); List<Long> stringList=sub_list.stream().map(Org::getId).collect(Collectors.toList()); String ids=StringUtils.join(stringList,","); //所有的左值大于新父节点的右值,左右值都加上偏移量 CusPara cusPara=new CusPara(); cusPara.setStrSet(String.format(" lft_val=lft_val + %s , rgt_val= rgt_val+ %s " , move,move)); cusPara.setStrWhere(String.format(" and lft_val>%s " , p_rgt,ids)); int other_num=orgDAO.updateCus(cusPara); } }else { throw new RuntimeException("1012更新当前节点失败!"); } }else { //所有的左值大于新父节点的右值,左值都加上偏移量 int other_l_num=orgDAO.updateCus(new CusPara() .setStrSet(String.format(" lft_val=lft_val + %s " ,move)) .setStrWhere(String.format(" and lft_val> %s" , p_rgt))); //所有的右值大于新父节点的右值,右值都加上偏移量 int other_r_num=orgDAO.updateCus(new CusPara() .setStrSet(String.format(" rgt_val=rgt_val + %s " ,move)) .setStrWhere(String.format(" and rgt_val>= %s" , p_rgt))); if(other_r_num>0){ //更新当前节点 int num=orgDAO.update(org); if(num>0){ if(sub_list.size()>0){ //更新当前节点原来子孙节点 int sub_num= orgDAO.updateCus(new CusPara() .setStrSet(String.format(" lft_val=lft_val + %s , rgt_val=rgt_val + %s " , move,move)) .setStrWhere(String.format(" and lft_val> %s and rgt_val< %s " , old_lft,old_rgt))); if(sub_num<=0){ throw new RuntimeException("1015更新子孙节点失败!"); } } }else { throw new RuntimeException("1017更新当前节点失败!"); } }else { throw new RuntimeException("1016更新其它节点失败!"); } } } } }