Skip to content

Commit

Permalink
feat: 增加树数据结构及其相关操作
Browse files Browse the repository at this point in the history
  • Loading branch information
ClearXs committed Nov 11, 2023
1 parent f63e8dc commit 0cab224
Show file tree
Hide file tree
Showing 25 changed files with 532 additions and 213 deletions.
2 changes: 2 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@
<version>1.1.5.RELEASE</version>
<description>构建大型应用需要的基本能力 --- all in one</description>
<url>https://github.com/b6688c/uno</url>

<developers>
<developer>
<name>j.x</name>
<email>jiangw1027@gmail.com</email>
</developer>
</developers>

<modules>
<module>uno-bom</module>
<module>uno-core</module>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,31 +1,28 @@
package cc.allio.uno.rule.api.vistor;
package cc.allio.uno.core.datastructure.tree;

import cc.allio.uno.core.util.CollectionUtils;

import java.util.LinkedList;
import java.util.Queue;

/**
* 广度优先
* 树广度优先
*
* @author jiangwei
* @date 2023/4/27 09:17
* @since 1.1.4
*/
public class BreadthTraversalMode implements TraversalMode {

BreadthTraversalMode() {
}

@Override
public void doTraversal(TraversalElement e, Visitor visitor) {
Queue<TraversalElement> bfsQueue = new LinkedList<>();
bfsQueue.add(e);
while (!bfsQueue.isEmpty()) {
TraversalElement element = bfsQueue.poll();
element.doAccept(visitor);
if (CollectionUtils.isNotEmpty(element.getChildrens())) {
element.getChildrens().forEach(bfsQueue::offer);
if (CollectionUtils.isNotEmpty(element.getChildren())) {
element.getChildren().forEach(chd -> bfsQueue.offer((TraversalElement) chd));
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package cc.allio.uno.rule.api.vistor;
package cc.allio.uno.core.datastructure.tree;

import cc.allio.uno.core.util.CollectionUtils;

Expand All @@ -15,26 +15,23 @@
*/
public class DeepTraversalMode implements TraversalMode {

DeepTraversalMode() {
}

@Override
public void doTraversal(TraversalElement e, Visitor visitor) {
// 深度优先
Deque<TraversalElement> dfsStack = new ArrayDeque<>();
dfsStack.push(e);
List<TraversalElement> childrens = e.getChildrens();
List<TraversalElement> childrens = e.getChildren();
deepAccept(childrens, dfsStack);
while (!dfsStack.isEmpty()) {
TraversalElement element = dfsStack.pollLast();
element.doAccept(visitor);
}
}

private void deepAccept(List<TraversalElement> childrens, Deque<TraversalElement> dfsStack) {
private void deepAccept(List<? extends TraversalElement> childrens, Deque<TraversalElement> dfsStack) {
if (CollectionUtils.isNotEmpty(childrens)) {
childrens.forEach(dfsStack::offerLast);
childrens.forEach(e -> deepAccept(e.getChildrens(), dfsStack));
childrens.forEach(e -> deepAccept(e.getChildren(), dfsStack));
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package cc.allio.uno.core.datastructure.tree;

import com.google.common.collect.Lists;
import lombok.Getter;
import lombok.NonNull;
import lombok.Setter;

import java.io.Serializable;
import java.util.List;

/**
* 默认树结点
*
* @author j.x
* @date 2023/11/9 11:36
* @since 1.1.5
*/
@Getter
public class DefaultElement extends TraversalElement {

private final Serializable id;
@Setter
private int depth;

@Setter
private Element parent;

private final List<Element> children;

public DefaultElement(@NonNull Serializable id) {
this.id = id;
this.children = Lists.newArrayList();
}

public DefaultElement(@NonNull Serializable id, int depth) {
this.id = id;
this.depth = depth;
this.children = Lists.newArrayList();
}

@Override
public boolean isLeaf() {
return children.isEmpty();
}

@Override
public <T extends Element> void setChildren(List<T> children) {
clearChildren();
this.children.addAll(children);
}

@Override
public void addChildren(Element element) {
children.add(element);
}

@Override
public void clearChildren() {
children.clear();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package cc.allio.uno.core.datastructure.tree;

import java.io.Serializable;

public record DefaultExpand(Serializable id, Serializable parentId) implements Expand {
@Override
public Serializable getId() {
return id;
}

@Override
public Serializable getParentId() {
return parentId;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package cc.allio.uno.core.datastructure.tree;

import cc.allio.uno.core.StringPool;

import java.io.Serializable;
import java.util.List;

/**
* 节点类型分为两种:
* <ul>
* <li>group 节点</li>
* <li>attr 节点</li>
* </ul>
*
* @author jiangwei
* @date 2023/4/26 11:31
* @since 1.1.4
*/
public interface Element extends Serializable {

Element ROOT_SENTINEL = new DefaultElement(-1, -1);

/**
* 定义根节点
*/
int ROOT_NODE = 0;

/**
* 获取树的标识
*/
Serializable getId();

/**
* 获取节点所在的深度
*
* @return level
*/
int getDepth();

/**
* 设置树的层级
*/
void setDepth(int depth);

/**
* 获取当前树的路径
*
* @return a.b.c以'.'来切分路径标识
*/
default String getPath() {
return getParent() != null ? getParent().getPath() + StringPool.ORIGIN_DOT + getId() : String.valueOf(getId());
}

/**
* 获取父节点
*
* @return Element
*/
<T extends Element> T getParent();

/**
* 设置父节点
*
* @param parent parent node
*/
<T extends Element> void setParent(T parent);

/**
* 是否为根节点
*
* @return true 是 false 否
*/
default boolean isRoot() {
return getDepth() == ROOT_NODE;
}

/**
* 是否为叶子节点
*
* @return true 是 false 否
*/
boolean isLeaf();

/**
* 获取子节点
*
* @return element list
*/
<T extends Element> List<T> getChildren();

/**
* 添加子结点
*/
<T extends Element> void addChildren(T element);

/**
* 覆盖并设置子结点
*
* @param children children
*/
<T extends Element> void setChildren(List<T> children);

/**
* 清除children数据
*/
void clearChildren();

/**
* 访问器模式访问每一个节点。默认实现为深度优先原则
*
* @param visitor visitor
*/
default void accept(Visitor visitor) {
accept(visitor, Traversal.NONE);
}

/**
* 访问器模式访问每一个节点。默认实现为深度优先原则
*
* @param visitor visitor
* @param traversal 遍历原则
*/
void accept(Visitor visitor, Traversal traversal);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package cc.allio.uno.core.datastructure.tree;

import java.io.Serializable;

/**
* 树平展结点
*
* @author j.x
* @date 2023/11/9 11:32
* @since 1.1.5
*/
public interface Expand {

/**
* 获取当前结点的标识
*/
Serializable getId();

/**
* 获取父节点标识
*/
Serializable getParentId();
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package cc.allio.uno.rule.api.vistor;
package cc.allio.uno.core.datastructure.tree;

/**
* 优先访问枝干
Expand All @@ -14,7 +14,7 @@ public class NoneTraversalMode implements TraversalMode {
@Override
public void doTraversal(TraversalElement e, Visitor visitor) {
e.doAccept(visitor);
e.getChildrens().forEach(c -> c.accept(visitor, getMode()));
e.getChildren().forEach(c -> c.accept(visitor, getMode()));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package cc.allio.uno.rule.api.vistor;
package cc.allio.uno.core.datastructure.tree;

/**
* 规则树遍历方式
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
package cc.allio.uno.rule.api.vistor;

import java.util.*;
package cc.allio.uno.core.datastructure.tree;

/**
* 遍历元素原则实现.{@link Traversal}
Expand All @@ -16,13 +14,6 @@ public void accept(Visitor visitor, Traversal traversal) {
TraversalMode.get(traversal).doTraversal(this, visitor);
}

/**
* 获取子节点
*
* @return element list
*/
protected abstract List<TraversalElement> getChildrens();

/**
* 子类可以继承实现,默认调用访问访问当前元数据
*
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package cc.allio.uno.rule.api.vistor;
package cc.allio.uno.core.datastructure.tree;

import cc.allio.uno.core.exception.Exceptions;

Expand Down
Loading

0 comments on commit 0cab224

Please sign in to comment.