广告位联系
返回顶部
分享到

Java二叉树的实现和遍历介绍

java 来源:互联网 作者:秩名 发布时间:2022-01-28 21:03:44 人浏览
摘要

什么是二叉树 简单理解为对于一个节点来说,最多拥有一个上级节点,同时最多具备左右两个下级节点的数据结构。 由于很多排序算法都是基于二叉树实现的,多叉树也是二叉树延伸

什么是二叉树

简单理解为对于一个节点来说,最多拥有一个上级节点,同时最多具备左右两个下级节点的数据结构。

由于很多排序算法都是基于二叉树实现的,多叉树也是二叉树延伸过去的,所以二叉树的建树和遍历就显得非常重要。

二叉树建树

一般情况是给你一个串,要求让你以前序,中序,后序的方式建树。那么此时我们就需要首先了解三个概念:

  • 前序遍历
  • 中序遍历
  • 后序遍历

我们来看看一棵二叉树的结构:

0

1 2

3 4 5 6

0就是整个二叉树的根节点,1就是0这个节点的左子树,2就是0这个节点的右子树。有了这个知识,我们就可以理解前中后序遍历这个位置属性就是指的根在哪个位置,前序遍历就是根在前,所以就是根左子树右子树的遍历方式;中序遍历就是根在中间,所以就是左子树根右子树的遍历方式;后序遍历就是根在最后,所以就是左子树右子树根的遍历方式。

遍历的方式有三种,对应的建树方式有已知中序和前序建树,已知中序和后序建树,已知前序和后序建树三种。

如果我们仅仅是想构建一棵二叉平衡树,可以简单使用某一种序列建树。用伪代码表示这三种遍历方式就是

1.前序遍历的方式建树

1

2

3

new Tree(根节点);

buildTree(左子树);

buildTree(右子树);

2.中序遍历的方式建树

1

2

3

buildTree(左子树);

new Tree(根节点);

buildTree(右子树);

3.后序遍历的方式建树

1

2

3

buildTree(左子树);

buildTree(右子树);

new Tree(根节点);

前序建树

我们现在以序列 1, 2, 3, 4, 5, 6, 7, 8, 9 为例,如果是前序建树方式,那么二叉树的结构应该为:

实现也比较简单

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

package com.chaojilaji.book.tree;

 

import com.chaojilaji.auto.autocode.utils.Json;

 

public class Handle {

 

    /**

     * 前序建树

     *

     * @param input

     * @param index

     * @return

     */

    public static Tree buildTreePrologue(int[] input, int index) {

        // TODO: 2022/1/12 根节点就是当前index这个节点

        Tree tree = new Tree();

        tree.setValue(input[index]);

        // TODO: 2022/1/12 左右两个节点分别为 2*index-1和2*index+1

        int[] children = new int[]{2 * index + 1, 2 * index + 2};

        if (children[0] < input.length) {

            tree.setLeftChild(buildTreePrologue(input, children[0]));

        }

        if (children[1] < input.length) {

            tree.setRightChild(buildTreePrologue(input, children[1]));

        }

        return tree;

    }

 

 

    public static void demo() {

        int[] a = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9};

        Tree tree = buildTreePrologue(a, 0);

        System.out.println(Json.toJson(tree));

 

    }

 

    public static void main(String[] args) {

        demo();

    }

}

执行结果如下:

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

{

    "value": 1,

    "left_child": {

        "value": 2,

        "left_child": {

            "value": 4,

            "left_child": {

                "value": 8,

                "left_child": null,

                "right_child": null

            },

            "right_child": {

                "value": 9,

                "left_child": null,

                "right_child": null

            }

        },

        "right_child": {

            "value": 5,

            "left_child": null,

            "right_child": null

        }

    },

    "right_child": {

        "value": 3,

        "left_child": {

            "value": 6,

            "left_child": null,

            "right_child": null

        },

        "right_child": {

            "value": 7,

            "left_child": null,

            "right_child": null

        }

    }

}

中序建树

以 1,2,3,4,5,6,7序列为例,如果是中序建树的方式,那么二叉树的结构应该为

代码如下:

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

package com.chaojilaji.book.tree;

 

import com.chaojilaji.auto.autocode.utils.Json;

import com.chaojilaji.auto.autocode.utils.MathUtils;

 

import java.util.LinkedList;

import java.util.Objects;

import java.util.Queue;

 

public class Handle {

 

    /**

     * 中序建树

     * @param input

     * @param height

     * @param maxHeight

     * @return

     */

    public static Tree buildTree2(Queue<Integer> input, int height, int maxHeight) {

        // TODO: 2022/1/12 根节点就是当前index这个节点

        Tree tree = new Tree();

 

        if (height < maxHeight) {

            tree.setLeftChild(buildTree2(input, height + 1, maxHeight));

        }

        if (!input.isEmpty()) {

            tree.setValue(input.poll());

        }

        if (height < maxHeight) {

            tree.setRightChild(buildTree2(input, height + 1, maxHeight));

        }

        return tree;

    }

 

    public static void demo() {

        int[] a = new int[]{1, 2, 3, 4, 5, 6, 7};

        Queue<Integer> queue = new LinkedList<>();

        for (int i = 0; i < a.length; i++) {

            queue.add(a[i]);

        }

        Integer maxCeng = new Double(Math.ceil(MathUtils.getLogAN(2, a.length + 1))).intValue();

        System.out.println(Json.toJson(buildTree2(queue, 1, maxCeng)));

    }

 

    public static void main(String[] args) {

        demo();

    }

}

相对前序建树以扩展的方式建立二叉树,中序建树由于无法很好的控制索引,所以这里使用了一个队列来存储整个序列,同时需要算出以当前的节点数,算出建立一棵二叉平衡树,最小的深度为多少。然后按照之前给出的伪代码,按照左根右的方式赋值和递归调用即可。
运行的结果如下:

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

{

    "value": 4,

    "left_child": {

        "value": 2,

        "left_child": {

            "value": 1,

            "left_child": null,

            "right_child": null

        },

        "right_child": {

            "value": 3,

            "left_child": null,

            "right_child": null

        }

    },

    "right_child": {

        "value": 6,

        "left_child": {

            "value": 5,

            "left_child": null,

            "right_child": null

        },

        "right_child": {

            "value": 7,

            "left_child": null,

            "right_child": null

        }

    }

}

后序建树

有了中序遍历,其实后序遍历就非常简单了,以序列1,2,3,4,5,6,7为例,建树应该为

代码如下:

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

package com.chaojilaji.book.tree;

 

import com.chaojilaji.auto.autocode.utils.Json;

import com.chaojilaji.auto.autocode.utils.MathUtils;

 

import java.util.LinkedList;

import java.util.Objects;

import java.util.Queue;

 

public class Handle {

 

    /**

     * 后序建树

     *

     * @return

     */

    public static Tree buildTree3(Queue<Integer> input, int height, int maxHeight) {

        // TODO: 2022/1/12 根节点就是当前index这个节点

        Tree tree = new Tree();

 

        if (height < maxHeight) {

            tree.setLeftChild(buildTree3(input, height + 1, maxHeight));

        }

 

        if (height < maxHeight) {

            tree.setRightChild(buildTree3(input, height + 1, maxHeight));

        }

        if (!input.isEmpty()) {

            tree.setValue(input.poll());

        }

        return tree;

    }

 

    public static void demo() {

        int[] a = new int[]{1, 2, 3, 4, 5, 6, 7};

        Queue<Integer> queue = new LinkedList<>();

        for (int i = 0; i < a.length; i++) {

            queue.add(a[i]);

        }

        Integer maxCeng = new Double(Math.ceil(MathUtils.getLogAN(2, a.length + 1))).intValue();                                                    

        System.out.println(Json.toJson(buildTree3(queue, 1, maxCeng)));

 

    }

 

    public static void main(String[] args) {

        demo();

    }

 

 

}

通过分析三个建树方法的代码你可以发现,其实本质上,根赋值代码,与调用左右子树建树函数的摆放的位置不同,就早就了这三种不同的算法。

三种建树方法对应的三种遍历方法本质区别也就是打印值语句与调用左右子树打印值函数的摆放位置不同。如果举一反三的话,我们可以很容易的得出二叉树前中后序遍历的代码。那么,请你自己先尝试一下。

二叉树的遍历

根据建树的经验,知道,我们只需要写出一种遍历方法,那么其他两种遍历方式都有了。区别只不过是换换打印语句的位置。
对于前序遍历,写法如下:

1

2

3

4

5

6

7

8

9

10

11

12

public static void print1(Tree tree) {

    if (Objects.isNull(tree)) return;

    if (Objects.nonNull(tree.getValue())) {

        System.out.print(tree.getValue());

    }

    if (Objects.nonNull(tree.getLeftChild())) {

        print1(tree.getLeftChild());

    }

    if (Objects.nonNull(tree.getRightChild())) {

        print1(tree.getRightChild());

    }

}

那么我们来做一个实验,首先根据序列1,2,3,4,5,6,7利用前序遍历构建出一棵平衡二叉树,然后打印出其前序中序后序遍历的顺序。完整的代码如下:

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

package com.chaojilaji.book.tree;

 

import com.chaojilaji.auto.autocode.utils.Json;

import com.chaojilaji.auto.autocode.utils.MathUtils;

 

import java.util.LinkedList;

import java.util.Objects;

import java.util.Queue;

 

public class Handle {

 

 

    /**

     * 前序建树

     *

     * @param input

     * @param index

     * @return

     */

    public static Tree buildTreePrologue(int[] input, int index) {

        // TODO: 2022/1/12 根节点就是当前index这个节点

        Tree tree = new Tree();

        tree.setValue(input[index]);

        // TODO: 2022/1/12 左右两个节点分别为 2*index-1和2*index+1

        int[] children = new int[]{2 * index + 1, 2 * index + 2};

        if (children[0] < input.length) {

            tree.setLeftChild(buildTreePrologue(input, children[0]));

        }

        if (children[1] < input.length) {

            tree.setRightChild(buildTreePrologue(input, children[1]));

        }

        return tree;

    }

 

    /**

     * 中序建树

     *

     * @param input

     * @param height

     * @param maxHeight

     * @return

     */

    public static Tree buildTree2(Queue<Integer> input, int height, int maxHeight) {

        // TODO: 2022/1/12 根节点就是当前index这个节点

        Tree tree = new Tree();

 

        if (height < maxHeight) {

            tree.setLeftChild(buildTree2(input, height + 1, maxHeight));

        }

        if (!input.isEmpty()) {

            tree.setValue(input.poll());

        }

        if (height < maxHeight) {

            tree.setRightChild(buildTree2(input, height + 1, maxHeight));

        }

        return tree;

    }

 

    /**

     * 后序建树

     *

     * @return

     */

    public static Tree buildTree3(Queue<Integer> input, int height, int maxHeight) {

        // TODO: 2022/1/12 根节点就是当前index这个节点

        Tree tree = new Tree();

 

        if (height < maxHeight) {

            tree.setLeftChild(buildTree3(input, height + 1, maxHeight));

        }

 

        if (height < maxHeight) {

            tree.setRightChild(buildTree3(input, height + 1, maxHeight));

        }

        if (!input.isEmpty()) {

            tree.setValue(input.poll());

        }

        return tree;

    }

 

    public static void print1(Tree tree) {

        if (Objects.isNull(tree)) return;

        if (Objects.nonNull(tree.getValue())) {

            System.out.print(tree.getValue());

        }

        if (Objects.nonNull(tree.getLeftChild())) {

            print1(tree.getLeftChild());

        }

        if (Objects.nonNull(tree.getRightChild())) {

            print1(tree.getRightChild());

        }

    }

 

    public static void print2(Tree tree) {

        if (Objects.isNull(tree)) return;

        if (Objects.nonNull(tree.getLeftChild())) {

            print2(tree.getLeftChild());

        }

        if (Objects.nonNull(tree.getValue())) {

            System.out.print(tree.getValue());

        }

        if (Objects.nonNull(tree.getRightChild())) {

            print2(tree.getRightChild());

        }

    }

 

    public static void print3(Tree tree) {

        if (Objects.isNull(tree)) return;

        if (Objects.nonNull(tree.getLeftChild())) {

            print3(tree.getLeftChild());

        }

        if (Objects.nonNull(tree.getRightChild())) {

            print3(tree.getRightChild());

        }

        if (Objects.nonNull(tree.getValue())) {

            System.out.print(tree.getValue());

        }

    }

 

    public static void demoPrint() {

        int[] a = new int[]{1, 2, 3, 4, 5, 6, 7};

        Tree tree = buildTreePrologue(a, 0);

        print1(tree);

        System.out.println();

        print2(tree);

        System.out.println();

        print3(tree);

    }

 

    public static void main(String[] args) {

        demoPrint();

    }

}

最终的结果如下:


版权声明 : 本文内容来源于互联网或用户自行发布贡献,该文观点仅代表原作者本人。本站仅提供信息存储空间服务和不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权, 违法违规的内容, 请发送邮件至2530232025#qq.cn(#换@)举报,一经查实,本站将立刻删除。
原文链接 : https://blog.csdn.net/xielinrui123/article/details/122628942
相关文章
  • SpringBoot自定义错误处理逻辑介绍

    SpringBoot自定义错误处理逻辑介绍
    1. 自定义错误页面 将自定义错误页面放在 templates 的 error 文件夹下,SpringBoot 精确匹配错误信息,使用 4xx.html 或者 5xx.html 页面可以打印错误
  • Java实现手写一个线程池的代码

    Java实现手写一个线程池的代码
    线程池技术想必大家都不陌生把,相信在平时的工作中没有少用,而且这也是面试频率非常高的一个知识点,那么大家知道它的实现原理和
  • Java实现断点续传功能的代码

    Java实现断点续传功能的代码
    题目实现:网络资源的断点续传功能。 二、解题思路 获取要下载的资源网址 显示网络资源的大小 上次读取到的字节位置以及未读取的字节
  • 你可知HashMap为什么是线程不安全的
    HashMap 的线程不安全 HashMap 的线程不安全主要体现在下面两个方面 在 jdk 1.7 中,当并发执行扩容操作时会造成环形链和数据丢失的情况 在
  • ArrayList的动态扩容机制的介绍

    ArrayList的动态扩容机制的介绍
    对于 ArrayList 的动态扩容机制想必大家都听说过,之前的文章中也谈到过,不过由于时间久远,早已忘却。 所以利用这篇文章做做笔记,加
  • JVM基础之字节码的增强技术介绍

    JVM基础之字节码的增强技术介绍
    字节码增强技术 在上文中,着重介绍了字节码的结构,这为我们了解字节码增强技术的实现打下了基础。字节码增强技术就是一类对现有字
  • Java中的字节码增强技术

    Java中的字节码增强技术
    1.字节码增强技术 字节码增强技术就是一类对现有字节码进行修改或者动态生成全新字节码文件的技术。 参考地址 2.常见技术 技术分类 类
  • Redis BloomFilter布隆过滤器原理与实现

    Redis BloomFilter布隆过滤器原理与实现
    Bloom Filter 概念 布隆过滤器(英语:Bloom Filter)是1970年由一个叫布隆的小伙子提出的。它实际上是一个很长的二进制向量和一系列随机映射
  • Java C++算法题解leetcode801使序列递增的最小交换次

    Java C++算法题解leetcode801使序列递增的最小交换次
    题目要求 思路:状态机DP 实现一:状态机 Java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class Solution { public int minSwap(int[] nums1, int[] nums2) { int n
  • Mybatis结果集映射与生命周期介绍

    Mybatis结果集映射与生命周期介绍
    一、ResultMap结果集映射 1、设计思想 对简单的语句做到零配置,对于复杂一点的语句,只需要描述语句之间的关系就行了 2、resultMap的应用场
  • 本站所有内容来源于互联网或用户自行发布,本站仅提供信息存储空间服务,不拥有版权,不承担法律责任。如有侵犯您的权益,请您联系站长处理!
  • Copyright © 2017-2022 F11.CN All Rights Reserved. F11站长开发者网 版权所有 | 苏ICP备2022031554号-1 | 51LA统计