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
头号玩家
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。