Java实现孩子兄弟树

1. 数据定义

具体孩子兄弟树的定义结构不再赘述。

@Data
@NoArgsConstructor
@AllArgsConstructor
public class TreeNode {


    private String value;

    private TreeNode childNode;

    private TreeNode broNode;

    public TreeNode(String value){
        this.value = value;
    }
}

2.树的实现

@Slf4j
public class TreeUtils {

    /**
     * 根
     */
    private static TreeNode root = new TreeNode();

    /**
     * 是不是root下的第一个孩子,因为孩子兄弟树是全左子树
     */
    private static Boolean isFirstChild = true;

    private static TreeNode currentParentNode = new TreeNode();

    /**
     * 单例构造
     * @param value
     * @return
     */
    public static TreeUtils getRoot(String value){
        root.setValue(value);
        return new TreeUtils();
    }

    public TreeUtils() {
    }

    /**
     * 造树的主要方法,先挂成子树,在挂到root
     * @param parentValue 父节点值
     * @param childValueList 子节点值
     */
    public void setChildNode(String parentValue, List<String> childValueList){

        // 子节点node的list
        List<TreeNode> childNodeList = new ArrayList<>();
        // 先生成子树
        TreeNode parentNode = new TreeNode(parentValue);
        TreeNode firstChildNode = new TreeNode(childValueList.remove(0));

        childNodeList.add(firstChildNode);
        parentNode.setChildNode(firstChildNode);
        for (String childValue : childValueList) {
            TreeNode childNode = new TreeNode(childValue);
            childNodeList.add(childNode);
            // 挂载
            firstChildNode.setBroNode(childNode);
            firstChildNode = firstChildNode.getBroNode();
        }

        // 挂到root
        if (isFirstChild){
            // 先挂root首个孩子
            root.setChildNode(parentNode);
            isFirstChild = false;
            // 更新当前最后一个父级节点的位置
            currentParentNode = root.getChildNode();
            log.info("root的第一个孩子挂载完成!");
        }else {
            // 不是第一个孩子,子树就挂在第一个孩子的兄弟节点上
            // 先查有没有相同value的父级点
            TreeNode repParentNode = getParentNode(parentValue);
            if (repParentNode != null){
                //有就把子树的节点挂到查到的节点上
                TreeNode lastChildNode = getLastChildNode(repParentNode);
                if (lastChildNode!=null){
                    //判空是为了防止相同值的单父节点,无子节点的情况
                    while (childNodeList.size()!=0){
                        lastChildNode.setBroNode(childNodeList.remove(0));
                        lastChildNode = lastChildNode.getBroNode();
                    }
                }else {
                    //有重复的父级,没子级,就把之前建的子树除了父节点都插进去
                    repParentNode.setChildNode(parentNode.getChildNode());
                }
            }else {
                // 没重复的父级,就把子树插在当前最后一个父节点的兄弟上
                currentParentNode.setBroNode(parentNode);
                currentParentNode = currentParentNode.getBroNode();
            }
        }

    }

    /**
     * 获取重复的父级节点
     * @param parentValue
     * @return 成功就返回相同节点,失败返回null
     */
    public TreeNode getParentNode(String parentValue){
            // root的首个孩子节点
            TreeNode parentNode = root.getChildNode();

            // 依次查此节点的兄弟
            while (parentNode!=null){
                if (parentValue.equals(parentNode.getValue())){
                    return parentNode;
                }else {
                    parentNode = parentNode.getBroNode();
                }
            }
        return null;
    }

    /**
     * 获得最后一个孩子节点
     * @param node
     * @return
     */
    public TreeNode getLastChildNode(TreeNode node){
        try {
            TreeNode childNode = node.getChildNode();
            while (childNode.getBroNode()!=null){
                childNode = childNode.getBroNode();
            }
            return childNode;
        }catch (Exception e){
            log.info("查找最后一个子节点出错!");
            e.printStackTrace();
        }
        return null;
    }


    private static List<TreeNode> preScanList = new ArrayList<>();
    /**
     * 先序遍历-添加到List
     * 孩子兄弟树的先序正好就是,先父后所有子
     */
    public void preScan(TreeNode node){
        if (node == null){
            return;
        }
        preScanList.add(node);
        preScan(node.getChildNode());
        preScan(node.getBroNode());
    }

    /**
     * 先序遍历-打印
     */
    public void printTree(TreeNode node){
        if (node == null){
            return;
        }
        System.out.println(node.getValue());
        printTree(node.getChildNode());
        printTree(node.getBroNode());
    }

    /**
     * 代理遍历整个树
     */
    public void printAllTree(){
        printTree(root);
    }

}

3. 测试

测试代码
@Test
public void buildTreeTest(){
    TreeUtils root = TreeUtils.getRoot("电影树");
    String father1 = "科幻片";
    List<String> child1 = new ArrayList<>();
    Collections.addAll(child1,"  星际穿越","  三体","  守望者");

    String father2 = "喜剧";
    List<String> child2 = new ArrayList<>();
    Collections.addAll(child2,"  低俗小说","  绿皮书","  让子弹飞");

    String father3 = "动作";
    List<String> child3 = new ArrayList<>();
    Collections.addAll(child3,"  蝙蝠侠:黑暗骑士","  LEON","  头号玩家");

    String father4 = "喜剧";
    List<String> child4 = new ArrayList<>();
    Collections.addAll(child4,"  人在囧途","  平原上的夏洛克");

    root.setChildNode(father1,child1);
    root.setChildNode(father2,child2);
    root.setChildNode(father3,child3);
    root.setChildNode(father4,child4);

    root.printAllTree();
}
结果
电影树
科幻片
  星际穿越
  三体
  守望者
喜剧
  低俗小说
  绿皮书
  让子弹飞
  人在囧途
  平原上的夏洛克
动作
  蝙蝠侠:黑暗骑士
  LEON
  头号玩家

深蓝
1 声望0 粉丝

下一篇 »
微博热榜爬虫