浅谈数据结构-树

相关文章链接:

相关文章链接 第2节 数据结构

观前提示:

本文所使用的IDEA版本为ultimate 2019.1,JDK版本为1.8.0_141。

1 基本概念

  1. :一种数据结构,它是由n(n>=1)个有限结点组成一个具有层次关系的集合。把它叫做“树”是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。

  2. 结点:每个元素称为结点(node)。

  3. 根结点:没有父结点的结点称为根结点。

  4. 结点的度:一个结点含有的子结点的个数称为该结点的度。

  5. 树的度:一棵树中,最大的结点的度称为树的度。

  6. 结点的层次:从根开始定义起,根为第1层,根的子结点为第2层,以此类推。

  7. 叶结点:度为0的结点称为叶结点。

  8. 树的高度或深度:树中结点的最大层次。

2 特点

  1. 每个结点有零个或多个子结点

  2. 没有父结点的结点称为根结点

  3. 每一个非根结点有且只有一个父结点

  4. 除了根结点外,每个子结点可以分为多个不相交的子树

3 种类

3.1 无序树

树中任意节点的子结点之间没有顺序关系,这种树称为无序树,也称为自由树。

3.2有序树

树中任意节点的子结点之间有顺序关系,这种树称为有序树。

3.3二叉树

每个节点最多含有两个子树的树称为二叉树。

3.4满二叉树

叶节点除外的所有节点均含有两个子树的树被称为满二叉树。

3.5完全二叉树

若设二叉树的深度为h,除第 h 层外,其它各层 (1~(h-1)层) 的结点数都达到最大个数,第h层所有的结点都连续集中在最左边,这就是完全二叉树。

3.6二叉排序树(二叉查找树,也称二叉搜索树)

一棵空树,或者是具有下列性质的二叉树

  • 若左子树不空,则左子树上所有结点的值均小于它的根结点的值。

  • 若右子树不空,则右子树上所有结点的值均大于它的根结点的值。

  • 左、右子树也分别为二叉排序树。

  • 没有键值相等的结点。

3.7 哈夫曼树(最优二叉树)

带权路径最短的二叉树称为哈夫曼树或最优二叉树。

3.8 AVL树(高度平衡树)

AVL树是最先发明的自平衡二叉查找树,在AVL树中任何节点的两个子树的高度最大差别为1,所以它也被称为高度平衡树。

3.9 红黑树

红黑树是一种特化的AVL树(平衡二叉树),都是在进行插入和删除操作时通过特定操作保持二叉查找树的平衡,从而获得较高的查找性能。其特点如下:

  • 节点是红色或黑色。

  • 根节点是黑色。

  • 所有叶子都是黑色。(叶子是NIL节点)

  • 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)

  • 从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。

3.10 B树

一棵m阶B树是一棵平衡的m路搜索树。它或者是空树,或者是满足下列性质的树:

  • 根结点至少有两个子女。

  • 每个非根节点所包含的关键字个数 j 满足:[m/2] - 1 <= j <= m - 1。

  • 除根结点以外的所有结点(不包括叶子结点)的度数正好是关键字总数加1,故内部子树个数 k 满足:[m/2] <= k <= m 。

  • 所有的叶子结点都位于同一层。

3.11 B+树

B+树是B树的一种变形形式,B+树上的叶子结点存储关键字以及相应记录的地址,叶子结点以上各层作为索引使用。一棵m阶的B+树定义如下:

  • 每个结点至多有m个子女。

  • 除根结点外,每个结点至少有[m/2]个子女,根结点至少有两个子女。

  • 有k个子女的结点必有k个关键字。

3.12 B* 树

B* 树是B+树的变体,在B+树的非根和非叶子结点再增加指向兄弟的指针;B* 树定义了非叶子结点关键字个数至少为(2/3)* M,即块的最低使用率为2/3(代替B+树的1/2)。

B* 树的分裂:当一个结点满时,如果它的下一个兄弟结点未满,那么将一部分数据移到兄弟结点中,再在原结点插入关键字,最后修改父结点中兄弟结点的关键字(因为兄弟结点的关键字范围改变了);如果兄弟也满了,则在原结点与兄弟结点之间增加新结点,并各复制1/3的数据到新结点,最后在父结点增加新结点的指针。

4.遍历

这里仅仅介绍二叉树的遍历,包括先序遍历、中序遍历、后序遍历、层次遍历

(借用网上随便找的一张二叉树的图讲解)
在这里插入图片描述

4.1 先序遍历

根结点->遍历左子树->遍历右子树(根->左->右)

顺序:根节点->前序遍历左子树->前序遍历右子树

结果为:ABCDEF

4.2 中序遍历

遍历左子树->根结点->遍历右子树(左->根->右)

顺序:中序遍历左子树->根节点->中序遍历右子树

结果为:CBDAEF

4.3 后序遍历

遍历左子树->遍历右子树->根结点(左->右->根)

顺序:后序遍历左子树->后序遍历右子树->根节点

结果为:CDBFEA

4.4 层次遍历

按层次从左到右遍历

结果为:ABECDF

4.5 java代码实例

自定义节点TreeNode.java

package TestTree;

/**
 * 自定义树节点
 * @author jjy
 * @date 2020-10-14
 */
public class TreeNode {

    private String root;
    private TreeNode left;
    private TreeNode right;

    public TreeNode() {
    }

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

    public String getRoot() {
        return root;
    }

    public void setRoot(String root) {
        this.root = root;
    }

    public TreeNode getLeft() {
        return left;
    }

    public void setLeft(TreeNode left) {
        this.left = left;
    }

    public TreeNode getRight() {
        return right;
    }

    public void setRight(TreeNode right) {
        this.right = right;
    }
}

工具类TraversalUtil.java

package TestTree;

import java.util.ArrayList;
import java.util.List;

/**
 * 二叉树遍历Util
 * @author jjy
 * @date 2020-10-14
 */
public class TraversalUtil {

    private static List<String> list;

    public static void init(){
        list = new ArrayList<>();
    }

    /**
     * 先序遍历
     * @param node
     * @return
     */
    public static List<String> preOrder(TreeNode node){
        if(node != null){
            list.add(node.getRoot());
            preOrder(node.getLeft());
            preOrder(node.getRight());
        }
        return list;
    }

    /**
     * 中序遍历
     * @param node
     * @return
     */
    public static List<String> inOrder(TreeNode node){
        if(node != null){
            inOrder(node.getLeft());
            list.add(node.getRoot());
            inOrder(node.getRight());
        }
        return list;
    }

    /**
     * 后序遍历
     * @param node
     * @return
     */
    public static List<String> postOrder(TreeNode node){
        if(node != null){
            postOrder(node.getLeft());
            postOrder(node.getRight());
            list.add(node.getRoot());
        }
        return list;
    }
}

测试类TestTraversal.java

package TestTree;

import java.util.List;

public class TestTraversal {
    public static void main(String[] args) {
        TreeNode t1 = new TreeNode("A");
        TreeNode t2 = new TreeNode("B");
        TreeNode t3 = new TreeNode("E");
        TreeNode t4 = new TreeNode("C");
        TreeNode t5 = new TreeNode("D");
        TreeNode t6 = new TreeNode("F");
        t2.setLeft(t4);
        t2.setRight(t5);
        t3.setRight(t6);
        t1.setLeft(t2);
        t1.setRight(t3);

        TraversalUtil.init();
        List<String> preList = TraversalUtil.preOrder(t1);
        System.out.println("先序排列结果为:");
        preList.forEach(System.out::print);

        TraversalUtil.init();
        List<String> inList = TraversalUtil.inOrder(t1);
        System.out.println("\n中序排列结果为:");
        inList.forEach(System.out::print);

        TraversalUtil.init();
        List<String> postList = TraversalUtil.postOrder(t1);
        System.out.println("\n后序排列结果为:");
        postList.forEach(System.out::print);
    }
}

结果为
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值