树结构中的节点增删改操作后,排序码的重新设置

package com.naydog.sort.bysortkey;

import java.util.ArrayList;
import java.util.List;

/**
 * 目的:树结构中一个节点下的子节点非自然排序,而是按照排序码。当发生节点增删,或位置移动时,需要重新设置排序码
 * 此为重新设置排序码的算法实现
 */
public class SortBySortKey {

    /**
     * 步长,相邻节点之间排序码相差10,即排序码是0,10,20,30...,而非0,1,2,3...
     */
    private int SORT_STEP = 10;

    /**
     * 
     * @param id
     * @param newPid 新的父节点
     * @param position 插入的位置
     */
    public void update(String id, String newPid, int position) {
        // 从repository获得对象
        E entity = null;//repository.findById(id);

        String oldPid = entity.getPid();

        entity.setPid(newPid);
        entity.setSortKey(position * SORT_STEP - 1); // 这里设置为步长的整数倍少一点很重要,在后面排序的时候可少传一些参数,少一些判断

        // 保存到repository
        // repository.save(entity);

        // 重新设置排序码
        if (!oldPid.equals(newPid)) { // 换了父节点,原先所在父节点也需要重排序
            sortBySortKey(oldPid);
        }
        sortBySortKey(newPid);
    }

    /**
     * 重新设置某一节点下子节点的排序码。分四种情况:
     * 原排序码:
     * 0, 10, 20, 30, 40
     * 插入后待排序的排序码(插入到第三个  +19):
     * 0, 10, 19, 20, 30, 40    直接重新按步长设置排序码
     * 移除后待排序的排序码(移除第三个 -20):
     * 0, 10, 30, 40                      直接重新按步长设置排序码
     * 从右往左移后待排序的排序码(第四个移到第二个 -30 +9):
     * 0, 9, 10, 20, 40               直接重新按步长设置排序码
     * 从左往右移动后待排序的排序码 (第二个移到第四个 -10 +29):
     * 0, 20, 29, 30, 40     29和30应该交换顺序,然后按步长设置排序码
     * 
     * @param pid
     */
    public void sortBySortKey(String pid) {
        // 某父节点下所有子节点(包括新插入的节点)
        List<E> siblings = null; //repository.findByPid(pid); 

        // 只需要对增加节点之后的节点重新设置排序码
        int unmatch = 0;
        boolean flag = false;
        List<E> needsSortList = new ArrayList<>();
        for (int i = 0; i < siblings.size(); i++) {
            E entity = siblings.get(i);
            if (entity.getSortKey() != i * SORT_STEP) { // 排序码和索引不一致,需要处理
                unmatch++;
                // 若第一个不匹配的数大于预期排序码(i*步长)则说明是删除或者是从左向右移动节点,标记之
                if (unmatch == 1 && entity.getSortKey() > i * SORT_STEP) { 
                    flag = true;
                }
                // 当设置了flag后,发现不能被步长整除的节点则表示当前为向右移的节点,此时要同时更新i与i+1 节点
                if (flag 
                        && (entity.getSortKey()) % SORT_STEP != 0 //当前为插入/修改位置的节点
                        && i < siblings.size() - 1) { // 后面还有节点
                    entity.setSortKey((i + 1) * SORT_STEP); // 两者要交换顺序
                    needsSortList.add(entity);
                    E tmpCtg2 = siblings.get(i + 1);
                    tmpCtg2.setSortKey(i * SORT_STEP);  // 两者要交换顺序
                    needsSortList.add(tmpCtg2);
                    unmatch++;
                    i++;
                } else { // 其余情况直接修改为步长的整数倍即可
                    entity.setSortKey(i * SORT_STEP);
                    needsSortList.add(entity);
                }
            }
        }

        // 更新
        //repository.saveAll(needsSortList);
    }

    public static void main(String[] args) {

    }

}

/**
 * 节点
 */
class E {
    private String id;
    private String pid;
    private int sortKey;

    public E(String id, String pid, int sortKey) {
        this.id = id;
        this.pid = pid;
        this.sortKey = sortKey;
    }
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getPid() {
        return pid;
    }
    public void setPid(String pid) {
        this.pid = pid;
    }
    public int getSortKey() {
        return sortKey;
    }
    public void setSortKey(int sortKey) {
        this.sortKey = sortKey;
    }
    @Override
    public String toString() {
        return "E [id=" + id + ", pid=" + pid + ", sortKey=" + sortKey + "]";
    }
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值