# 树以及应用

## 树的遍历

1）前序遍历：根->左->右；

2）中序遍历：左->根->右；

3）后序遍历：左->右->根。

### 前、中、后序遍历代码实现

class TreeNode {
private String name;
private TreeNode left;
private TreeNode right;

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

public TreeNode(String name, TreeNode left, TreeNode right) {
this.name = name;
this.left = left;
this.right = right;
}

... // 次数省去getter/setter
}

        TreeNode treeA = new TreeNode("A");
TreeNode treeB = new TreeNode("B");
TreeNode treeC = new TreeNode("C");
TreeNode treeD = new TreeNode("D");
TreeNode treeE = new TreeNode("E");
TreeNode treeF = new TreeNode("F");
TreeNode treeG = new TreeNode("G");
TreeNode treeH = new TreeNode("H");
TreeNode treeI = new TreeNode("I");
TreeNode treeJ = new TreeNode("J");
TreeNode treeK = new TreeNode("K");

treeA.setLeft(treeB);
treeA.setRight(treeC);

treeB.setLeft(treeD);
treeB.setRight(treeE);

treeC.setLeft(treeF);
treeC.setRight(treeG);

treeD.setRight(treeH);

treeE.setRight(treeI);

treeF.setLeft(treeJ);
treeF.setRight(treeK);

    /**
* 如果节点不为空，则打印节点name
*/
private static void printVal(TreeNode tree) {
if (tree != null) {
System.out.print("->" + tree.getName());
}
}

/**
* 前序遍历：根->左->右；
*/
private static void recursivePreOrder(TreeNode root) {
if (root == null) return;
printVal(root);
recursivePreOrder(root.getLeft());
recursivePreOrder(root.getRight());
}

/**
* 中序遍历：左->根->右；
*/
private static void recursiveInOrder(TreeNode root) {
if (root == null) return;
recursiveInOrder(root.getLeft());
printVal(root);
recursiveInOrder(root.getRight());
}

/**
* 后序遍历：左->右->根。
*/
private static void recursivePostOrder(TreeNode root) {
if (root == null) return;
recursivePostOrder(root.getLeft());
recursivePostOrder(root.getRight());
printVal(root);
}

main函数中执行对treeA进行前、中、后序遍历，并打印遍历结果：

    public static void main(String[] args) {
...// 此处省去上边treeA树填充代码

System.out.println("\r\n前序遍历：");
recursivePreOrder(treeA);

System.out.println("\r\n中序遍历：");
recursiveInOrder(treeA);

System.out.println("\r\n后序遍历：");
recursivePostOrder(treeA);
}

前序遍历：
->A->B->D->H->E->I->C->F->J->K->G

->D->H->B->E->I->A->J->F->K->C->G

->H->D->I->E->B->J->K->F->G->C->A

## 树的应用场景

1）前序遍历：用来实现目录结构的显示，比如：组织树；

2）中序遍历：用来做表达式树，在编译器底层实现的时候用户可以实现基本的加减乘除，比如：a*b+c；

3）后序遍历：用来实现计算机目录的文件占用的数据大小。

### 组织树

1）假设公司组织结构分为了以下4个目录：集团、中心、区域、分公司（实际上分公司下应该还有各自的部门等）。

2）前端当然是希望按照一定的顺序展示为一棵树（同层结构上排序自己可以定义，比如扩展TreeNode包含一个priority排序字段）；

3）当中心级别人员他可管理的人员只能是中心以下级别的人员，此时我们需要根据中心id获取其子组织节点id，然后根据这些子组织节点id去查询用户；

4）有时我们又希望查看父节点有哪些组织，此时需要根据用户所属组织节点向上查找父组织节点。

1）如果要查找A的子节点，那么需要查找min>1 and max<16的都是它的子节点，超找到的有B/C/D/E/F/G/H。

2）如果查找D节点的父节点，那么需要查钊min<3 and max>4的都是它的父节点，查找到的有A/B。

1）如果只是简单的每增加、删除（可以忽略不做维护）节点时，维护父级节点以及相邻节点的min/max值，几乎修改了整棵树的节点min/max值。

### 代码实现

static class TreeNode {
private Long id;
private String code;
private Long parentId;
private String name;
private Long lft;
private Long rht;

public TreeNode(Long id, String code, Long parentId, String name) {
this.id = id;
this.code = code;
this.parentId = parentId;
this.name = name;
}
...// 此处省去getter/setter
}

    static class NoFoundRootNodeException extends Exception {
public NoFoundRootNodeException(String message) {
super(message);
}
}

static class EmptyTreeException extends Exception {
public EmptyTreeException(String message) {
super(message);
}
}

        // 加载所有组织
final List<TreeNode> allOrgsList = new ArrayList<>();
// 集团

// 中心-01
// 区域-》中心-01
// 区域-》中心-01-》分公司

// 中心-02
// 区域-》中心-02
// 区域-》中心-02-》分公司

// 中心-03
// 区域-》中心-03
// 区域-》中心-03-》分公司

// 中心-04
// 区域-》中心-04
// 区域-》中心-04-》分公司
allOrgsList.add(new TreeNode(1004000200002L, "1004000200002L", 10040002L, "中心-04-区域-02-分公司-02"));

    /**
* 重置lft/rht值
*/
private static List<TreeNode> sortTreeNode(List<TreeNode> allOrgsList, String rootOrgCode) throws NoFoundRootNodeException, EmptyTreeException {
// 根组织
TreeNode rootOrg = null;
if (allOrgsList == null || allOrgsList.isEmpty()) {
throw new EmptyTreeException("empty org tree!");
}

for (TreeNode _org : allOrgsList) {
if (rootOrgCode.equals(_org.getCode())) {
rootOrg = _org;
break;
}
}

if (rootOrg == null) {
}

// 更新整棵组织树的lft和rht
List<TreeNode> treeList = new ArrayList<TreeNode>();
rootOrg.setLft(1L);
rootOrg.setRht(2L);

List<TreeNode> childList = new ArrayList<TreeNode>();
while (!childList.isEmpty()) {
System.out.println("-------------------------------------------------------------");
for (TreeNode treeNode : treeList) {
System.out.println(treeNode.getId() + "->" + treeNode.getParentId() + "" + treeNode.getCode() + "->" + treeNode.getName() + "->" + treeNode.getLft() + "->" + treeNode.getRht());
}

List<TreeNode> _childList = new ArrayList<TreeNode>();
childList.clear();

for (TreeNode _treeModel : _childList) {
List<TreeNode> tmpChildList = new ArrayList<TreeNode>();
Long _id = _treeModel.getId();
Long _pLft = _treeModel.getLft();

for (TreeNode _org : allOrgsList) {
if (_org.getParentId().longValue() == _id.longValue()) {
}
}

if (tmpChildList.isEmpty()) {
continue;
}

// 添加子节点
long _lft = _pLft + 1L;
for (TreeNode _org : tmpChildList) {
_org.setLft(_lft);
_org.setRht(_lft + 1L);

_lft += 2L;
}

// 更新已有节点
int _incr = tmpChildList.size() * 2;
for (TreeNode _model : treeList) {
if (_model.getLft().longValue() > _pLft.longValue()) {
_model.setLft(_model.getLft() + _incr);
}
if (_model.getRht().longValue() > _pLft.longValue()) {
_model.setRht(_model.getRht() + _incr);
}
}

tmpChildList.clear();
}
}

return treeList;
}

    public static void main(String[] args) {
// 加载所有组织
final List<TreeNode> allOrgsList = new ArrayList<>();
...// 此处省去填充代码

// 根组织code
final String rootOrgCode = "1";

// 同层按照id増序排序
allOrgsList.sort((s1, s2) -> {
return (int)(s1.getId() - s2.getId());
});

List<TreeNode> sortedTree = null;
try {
sortedTree = sortTreeNode(allOrgsList, rootOrgCode);
} catch (NoFoundRootNodeException e) {
e.printStackTrace();
} catch (EmptyTreeException e) {
e.printStackTrace();
}
}

-------------------------------------------------------------
1->01->集团->1->2
-------------------------------------------------------------
1->01->集团->1->10
1001->11001L->中心-01->2->3
1002->11002L->中心-02->4->5
1003->11003L->中心-03->6->7
1004->11004L->中心-04->8->9
-------------------------------------------------------------
1->01->集团->1->26
1001->11001L->中心-01->2->7
1002->11002L->中心-02->8->13
1003->11003L->中心-03->14->19
1004->11004L->中心-04->20->25
10010001->100110010001L->中心-01-区域-01->3->4
10010002->100110010002L->中心-01-区域-02->5->6
10020001->100210020001L->中心-02-区域-01->9->10
10020002->100210020002L->中心-02-区域-02->11->12
10030001->100310030001L->中心-03-区域-01->15->16
10030002->100310030002L->中心-03-区域-02->17->18
10040001->100410040001L->中心-04-区域-01->21->22
10040002->100410040002L->中心-04-区域-02->23->24
-------------------------------------------------------------
1->01->集团->1->60
1001->11001L->中心-01->2->15
1002->11002L->中心-02->16->29
1003->11003L->中心-03->30->45
1004->11004L->中心-04->46->59
10010001->100110010001L->中心-01-区域-01->3->8
10010002->100110010002L->中心-01-区域-02->9->14
10020001->100210020001L->中心-02-区域-01->17->22
10020002->100210020002L->中心-02-区域-02->23->28
10030001->100310030001L->中心-03-区域-01->31->36
10030002->100310030002L->中心-03-区域-02->37->44
10040001->100410040001L->中心-04-区域-01->47->52
10040002->100410040002L->中心-04-区域-02->53->58
1001000100001->100100011001000100001L->中心-01-区域-01-分公司-01->4->5
1001000100002->100100011001000100002L->中心-01-区域-01-分公司-02->6->7
1001000200001->100100021001000200001L->中心-01-区域-02-分公司-01->10->11
1001000200002->100100021001000200002L->中心-01-区域-02-分公司-02->12->13
1002000100001->100200011002000100001L->中心-02-区域-01-分公司-01->18->19
1002000100002->100200011002000100002L->中心-02-区域-01-分公司-02->20->21
1002000200001->100200021002000200001L->中心-02-区域-02-分公司-01->24->25
1002000200002->100200021002000200002L->中心-02-区域-02-分公司-02->26->27
1003000100001->100300011003000100001L->中心-03-区域-01-分公司-01->32->33
1003000100002->100300011003000100002L->中心-03-区域-01-分公司-02->34->35
1003000200001->100300021003000200001L->中心-03-区域-02-分公司-01->38->39
1003000200002->100300021003000200002L->中心-03-区域-02-分公司-02->40->41
1003000200002->100300021003000200003L->中心-03-区域-02-分公司-03->42->43
1004000100001->100400011004000100001L->中心-04-区域-01-分公司-01->48->49
1004000100002->100400011004000100002L->中心-04-区域-01-分公司-02->50->51
1004000200001->100400021004000200001L->中心-04-区域-02-分公司-01->54->55
1004000200002->100400021004000200002L->中心-04-区域-02-分公司-02->56->57

Process finished with exit code 0

posted @ 2021-01-18 21:43  cctext  阅读(156)  评论(0编辑  收藏  举报