# 顺序存储二叉树
# 基本说明-概念
从数据存储来看,数组存储 方式和 树 的存储方式可以 相互转换。即使数组可以转换成树,树也可以转换成数组。如下示意图
上图阅读说明:
- 圆圈顶部的数字对应了数组中的索引
- 圆圈内部的值对应的数数组元素的值
现在有两个要求:
- 上图的二叉树的节点,要求以数组的方式来存储
arr=[1,2,3,4,5,6,7]
- 要求在遍历数组 arr 时,仍然可以以 前序、中序、后序的方式遍历
# 特点
想要 实现上面的两个要求,需要知道顺序存储二叉树的特点:
- 顺序二叉树 通常只考虑 完全二叉树
- 第 n 个元素的 左子节点 为
2*n+1
- 第 n 个元素的 右子节点 为
2*n+2
- 第 n 个元素的 父节点 为
(n-1)/2
注:n 表示二叉树中的第几个元素(按 0 开始编号)
比如:
- 元素 2 的左子节点为:
2 * 1 + 1 = 3
,对比上图去查看,的确是 3 - 元素 2 的右子节点为:
2 * 1 + 2 = 4
,也 就是元素 5 - 元素 3 的左子节点为:
2 * 2 + 1 = 5
,也就是元素 6 - 元素 3 的父节点为:
(2-1)/2= 1/2 = 0
,也就是根节点 1
# 前序遍历
使用如上的知识点,进行前序遍历,需求:将数组 arr=[1,2,3,4,5,6,7]
,以二叉树前序遍历的方式进行遍历,遍历结果为 1、2、4、5、3、6
前序遍历概念(前面章节有学习过):
- 先输出当前节点(初始节点是 root 节点)
- 如果左子节点不为空,则递归继续前序遍历
- 如果右子节点不为空,则递归继续前序遍历
package cn.mrcode.study.dsalgtutorialdemo.datastructure.tree;
import org.junit.Test;
/**
* 顺序存储二叉树
*/
public class ArrBinaryTreeTest {
/**
* 前序遍历测试
*/
@Test
public void preOrder() {
int[] arr = new int[]{1, 2, 3, 4, 5, 6, 7};
ArrBinaryTree tree = new ArrBinaryTree(arr);
tree.preOrder(0); // 1,2,4,5,3,6,7
}
}
class ArrBinaryTree {
int[] arr;
public ArrBinaryTree(int[] arr) {
this.arr = arr;
}
/**
* 前序遍历
*
* @param index 就是知识点中的 n,从哪一个节点开始遍历
*/
public void preOrder(int index) {
/*
1. 顺序二叉树 通常只考虑 **完成二叉树**
2. 第 n 个元素的 **左子节点** 为 `2*n+1`
3. 第 n 个元素的 **右子节点** 为 `2*n+2`
4. 第 n 个元素的 **父节点** 为 `(n-1)/2`
*/
if (arr == null || arr.length == 0) {
System.out.println("数组为空,不能前序遍历二叉树");
return;
}
// 1. 先输出当前节点(初始节点是 root 节点)
System.out.println(arr[index]);
// 2. 如果左子节点不为空,则递归继续前序遍历
int left = 2 * index + 1;
if (left < arr.length) {
preOrder(left);
}
// 3. 如果右子节点不为空,则递归继续前序遍历
int right = 2 * index + 2;
if (right < arr.length) {
preOrder(right);
}
}
}
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
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
测试输出
1
2
4
5
3
6
7
1
2
3
4
5
6
7
2
3
4
5
6
7
# 应用案例
学回了顺序存储二叉树,那么它可以用来做什么呢?
八大排序算法中的 堆排序,就会使用到顺序存储二叉树。这个排序算法在后续章节的 树结构实际应用 章节中再讲解
# 中序、后序遍历
课外作业,请实现另外两种遍历方式
/**
* 中序遍历:先遍历左子树,再输出父节点,再遍历右子树
*
* @param index
*/
public void infixOrder(int index) {
if (arr == null || arr.length == 0) {
System.out.println("数组为空,不能前序遍历二叉树");
return;
}
int left = 2 * index + 1;
if (left < arr.length) {
infixOrder(left);
}
System.out.println(arr[index]);
int right = 2 * index + 2;
if (right < arr.length) {
infixOrder(right);
}
}
/**
* 后序遍历:先遍历左子树,再遍历右子树,最后输出父节点
*
* @param index
*/
public void postOrder(int index) {
if (arr == null || arr.length == 0) {
System.out.println("数组为空,不能前序遍历二叉树");
return;
}
int left = 2 * index + 1;
if (left < arr.length) {
postOrder(left);
}
int right = 2 * index + 2;
if (right < arr.length) {
postOrder(right);
}
System.out.println(arr[index]);
}
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
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
测试代码
/**
* 中序遍历测试
*/
@Test
public void infixOrder() {
int[] arr = new int[]{1, 2, 3, 4, 5, 6, 7};
ArrBinaryTree tree = new ArrBinaryTree(arr);
tree.infixOrder(0); // 4,2,5,1,6,3,7
}
/**
* 后序遍历测试
*/
@Test
public void postOrder() {
int[] arr = new int[]{1, 2, 3, 4, 5, 6, 7};
ArrBinaryTree tree = new ArrBinaryTree(arr);
tree.postOrder(0); // 4,5,2,6,7,3,1
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19