言成言成啊 | Kit Chen's Blog

N叉树的构建与遍历

发布于2025-08-02 13:41:28,更新于2025-08-03 15:36:57,标签:java  文章会持续修订,转载请注明来源地址:https://meethigher.top/blog

学习理论知识时,我们都是学习的二叉树。但是在实际场景中,却都是N叉树。此处记录一下N叉树的构建与遍历。

本文源码meethigher/java-tree-examples: 树相关的知识,示例代码使用Java实现

一、二叉树

二叉树:每个节点最多有两个子节点(左子节点和右子节点)。结构如下

1
2
3
4
5
    1
/ \
2 3
/ \ / \
4 5 6 7

遍历方式有三种

  • 前序遍历(根左右):由根开始
    • 1 2 4 5 3 6 7
  • 中序遍历(左根右):根放中间
    • 4 2 5 1 6 3 7
  • 后序遍历(左右根):由根结束
    • 4 5 2 6 7 3 1

Java代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
public class Tree {

public static class TreeNode {
public int value;
public TreeNode left;
public TreeNode right;

public TreeNode(int value, TreeNode left, TreeNode right) {
this.value = value;
this.left = left;
this.right = right;
}

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

/**
* 前序遍历
* 根左右
*/
public static void preOrderTraversal(TreeNode node) {
if (node == null) {
return;
}
System.out.print(node.value+" ");
preOrderTraversal(node.left);
preOrderTraversal(node.right);
}

/**
* 中序遍历
* 左根右
*/
public static void inOrderTraversal(TreeNode node) {
if (node == null) {
return;
}
inOrderTraversal(node.left);
System.out.print(node.value+" ");
inOrderTraversal(node.right);
}

/**
* 后序遍历
* 左右根
*/
public static void postOrderTraversal(TreeNode node) {
if (node == null) {
return;
}
postOrderTraversal(node.left);
postOrderTraversal(node.right);
System.out.print(node.value+" ");
}

public static void main(String[] args) {
/*
创建二叉树
1
/ \
2 3
/ \ / \
4 5 6 7
*/
TreeNode root = new Tree.TreeNode(1);
root.left = new TreeNode(2);
root.right = new TreeNode(3);
root.left.left = new TreeNode(4);
root.left.right = new TreeNode(5);
root.right.left = new TreeNode(6);
root.right.right = new TreeNode(7);

/*
前序遍历结果:
1 2 4 5 3 6 7
中序遍历结果:
4 2 5 1 6 3 7
后序遍历结果:
4 5 2 6 7 3 1
*/
System.out.println("前序遍历结果:");
preOrderTraversal(root);
System.out.println();

System.out.println("中序遍历结果:");
inOrderTraversal(root);
System.out.println();

System.out.println("后序遍历结果:");
postOrderTraversal(root);
System.out.println();
}
}

二、N叉树(通用树)

多叉树:每个节点可以有任意数量的子节点。

公司的组织机构,就是一个N叉树。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
公司
├─亚太区
│ ├─中国区
│ │ ├─上海分公司
│ │ │ ├─产品设计部
│ │ │ ├─人力资源部
│ │ │ ├─客服部
│ │ │ ├─市场部
│ │ │ ├─技术支持部
│ │ │ ├─数据分析部
│ │ │ ├─研发部
│ │ │ ├─财务部
│ │ │ ├─销售部
│ │ │ └─项目管理部
│ │ ├─北京分公司
│ │ │ ├─产品设计部
│ │ │ │ ├─产品设计小组A
│ │ │ │ └─产品设计小组B
│ │ │ ├─人力资源部
│ │ │ │ ├─员工关系小组
│ │ │ │ ├─培训小组
│ │ │ │ ├─招聘小组
│ │ │ │ └─绩效管理小组
│ │ │ ├─客服部
│ │ │ │ ├─客服团队A
│ │ │ │ └─客服团队B
│ │ │ ├─市场部
│ │ │ │ ├─品牌推广小组
│ │ │ │ ├─市场调研小组
│ │ │ │ └─广告策划小组
│ │ │ ├─技术支持部
│ │ │ │ ├─技术支持小组A
│ │ │ │ └─技术支持小组B
│ │ │ ├─数据分析部
│ │ │ │ ├─数据分析小组A
│ │ │ │ └─数据分析小组B
│ │ │ ├─研发部
│ │ │ │ ├─测试小组
│ │ │ │ ├─硬件开发小组
│ │ │ │ └─软件开发小组
│ │ │ ├─财务部
│ │ │ │ ├─会计小组
│ │ │ │ ├─审计小组
│ │ │ │ └─财务分析小组
│ │ │ ├─销售部
│ │ │ │ ├─销售团队A
│ │ │ │ ├─销售团队B
│ │ │ │ └─销售团队C
│ │ │ └─项目管理部
│ │ │ ├─项目管理小组A
│ │ │ └─项目管理小组B
│ │ └─深圳分公司
│ │ ├─产品设计部
│ │ ├─人力资源部
│ │ ├─客服部
│ │ ├─市场部
│ │ ├─技术支持部
│ │ ├─数据分析部
│ │ ├─研发部
│ │ ├─财务部
│ │ ├─销售部
│ │ └─项目管理部
│ └─日本区
│ ├─东京分公司
│ └─大阪分公司
├─北美区
│ ├─加拿大区
│ │ ├─多伦多分公司
│ │ └─温哥华分公司
│ └─美国区
│ ├─洛杉矶分公司
│ └─纽约分公司
└─欧洲区
├─德国区
│ ├─慕尼黑分公司
│ └─柏林分公司
└─法国区
├─巴黎分公司
└─里昂分公司

N叉树的遍历有两种

  • 深度优先(Depth-First Search),使用递归或者栈
  • 广度优先(Breadth-First Search),使用队列

二叉树的前序、中序、后序遍历,本质上就是N叉树的深度优先遍历而已。

Java 代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
import java.io.Serializable;
import java.util.*;

public class Tree {

public static class Org implements Serializable {
private String code;
private String name;
private String parentCode;
private String parentName;

// 以下两个字段用于组装树结构时使用
private Integer orgNum;
private List<Org> children = new ArrayList<>();

public Integer getOrgNum() {
return orgNum;
}

public void setOrgNum(Integer orgNum) {
this.orgNum = orgNum;
}

public String getCode() {
return code;
}

public void setCode(String code) {
this.code = code;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getParentCode() {
return parentCode;
}

public void setParentCode(String parentCode) {
this.parentCode = parentCode;
}

public String getParentName() {
return parentName;
}

public void setParentName(String parentName) {
this.parentName = parentName;
}

public List<Org> getChildren() {
return children;
}

public void setChildren(List<Org> children) {
this.children = children;
}
}

/**
* 深度优先遍历
* <p>
* 可以实现先根后子,或者先子后根
*/
public static void depthFirstTraversalTree(Org tree) {
// 判断是否为叶子节点,若是,则更新机构数量为0。若不是则继续递归。
if (tree.getChildren() == null || tree.getChildren().isEmpty()) {
tree.setOrgNum(0);
return;
}
int sum = tree.getChildren().size();
for (Org child : tree.getChildren()) {
// 放到递归前,遍历顺序就是先根后子
depthFirstTraversalTree(child);
// 放到递归后,遍历顺序就是先子后根
sum += child.getOrgNum();
}
tree.setOrgNum(sum);
}

/**
* 广度优先遍历
* <p>
* 即层序遍历
*/
public static void breadthFirstTraversal(Org root) {
if (root == null) {
return;
}

Queue<Org> queue = new LinkedList<>();
queue.add(root);

while (!queue.isEmpty()) {
Org current = queue.poll(); // 从队列中取出一个节点
System.out.println("Code: " + current.getCode() + ", Name: " + current.getName());
// 将当前节点的所有子节点加入队列
if (current.getChildren() != null) {
for (Org child : current.getChildren()) {
queue.add(child);
}
}
}
}

public static Org buildTree(List<Org> list) {
Org tree = new Org();
tree.setCode("root");
tree.setName("root");
Map<String, Org> codeToOrgMap = new HashMap<>();
for (Org org : list) {
codeToOrgMap.put(org.getCode(), org);
}
for (Org org : list) {
// 若为第一层节点,则直接追加进去
if (org.getParentCode() == null || org.getCode().equals(org.getParentCode())) {
tree.getChildren().add(org);
} else {
Org t = codeToOrgMap.get(org.getParentCode());
if (t != null) {
t.getChildren().add(org);
}
}
}
return tree;
}

}
发布:2025-08-02 13:41:28
修改:2025-08-03 15:36:57
链接:https://meethigher.top/blog/2025/n-tree/
标签:java 
付款码 打赏 分享
Shift+Ctrl+1 可控制工具栏