数据结构6:数

介绍

树(英语:tree)是一种抽象数据类型(ADT)或是实现这种抽象数据类型的数据结构,用来模拟具有树状结构性质的数据集合。它是由n(n>0)个有限节点组成一个具有层次关系的集合。类似于一个倒置的树。

它具有以下的特点:

  • 没有父节点的节点称为根节点,任何非空树只有一个根节点
  • 任意两个节点有且仅有唯一的一条路径连通
  • 除了根节点外,每个子节点可以分为多个不相交的子树
  • 树里面没有环路(cycle)

在这里插入图片描述
常用名词介绍:

  • 节点:树中的每个元素都可以统称为节点。
  • 根节点:顶层节点或者说没有父节点的节点。上图中 A 节点就是根节点。
  • 父节点:若一个节点含有子节点,则这个节点称为其子节点的父节点。上图中的 B 节点是 D 节点、E 节点的父节点。
  • 子节点:一个节点含有的子树的根节点称为该节点的子节点。上图中 D 节点、E 节点是 B 节点的子节点。
  • 兄弟节点:具有相同父节点的节点互称为兄弟节点。上图中 D 节点、E 节点的共同父节点是 B 节点,故 D 和 E 为兄弟节点。
  • 叶子节点:没有子节点的节点。上图中的 D、F、H、I 都是叶子节点。
  • 节点的高度:该节点到叶子节点的最长路径所包含的边数。
  • 节点的深度:根节点到该节点的路径所包含的边数
  • 节点的层数:节点的深度+1。
  • 树的高度:根节点的高度。

为什么需要树

它结合了另外两种数据结构的优点: 一种是顺序表,另一种是链表。在树中查找数据项的速度和在有序数组中查找一样快, 并且插入数据项和删除数据项的速度也和链表一样。

树的分类

  • 无序树
    树中任意节点的子节点之间没有顺序关系,这种树称为无序树,也称为自由树。
  • 有序树
    树中任意节点的子节点之间有顺序关系,这种树称为有序树。
  • 二叉树
    每个节点最多含有两个子树的树称为二叉树。
  • 完全二叉树
    对于一颗二叉树,假设其深度为d(d>1)。除了第d层外,其它各层的节点数目均已达最大值,且第d层所有节点从左向右连续地紧密排列,这样的二叉树被称为完全二叉树。
    在这里插入图片描述
    完全二叉树有一个很好的性质:父结点和子节点的序号有着对应关系。
    当根节点的值为 1 的情况下,若父结点的序号是 i,那么左子节点的序号就是 2i,右子节点的序号是 2i+1。这个性质使得完全二叉树利用数组存储时可以极大地节省空间,以及利用序号找到某个节点的父结点和子节点。
  • 满二叉树
    所有叶节点都在最底层的完全二叉树。如果一个二叉树的层数为 K,且结点总数是(2^k) -1 ,则它就是 满二叉树。
    在这里插入图片描述
  • 平衡二叉树
    1.可以是一颗空树
    2.如果不是空树,它的左右两个子树的高度差的绝对值不超过 1,并且左右两个子树都是一棵平衡二叉树。
    平衡二叉树的常用实现方法有:红黑树、AVL 树、替罪羊树、加权平衡树、伸展树 等。

在这里插入图片描述

  • 排序二叉树(二叉查找树(英语:Binary Search Tree))
    二叉排序树或者是一棵空树,或者是具有下列性质的二叉树:
    (1)若左子树不空,则左子树上所有结点的值均小于或等于它的根结点的值;
    (2)若右子树不空,则右子树上所有结点的值均大于或等于它的根结点的值;
    (3)左、右子树也分别为二叉排序树;
    也称二叉搜索树、有序二叉树。
    在这里插入图片描述
  • 霍夫曼树
    带权路径最短的二叉树称为哈夫曼树或最优二叉树。
  • B树
    一种对读写操作进行优化的自平衡的二叉查找树,能够保持数据有序,拥有多于两个子树。

树的实现(二叉树)

链式存储

和链表类似,二叉树的链式存储依靠指针将各个节点串联起来,不需要连续的存储空间。

每个节点包括三个属性:

  • 数据 data。data 不一定是单一的数据,根据不同情况,可以是多个具有不同类型的数据。
  • 左节点指针 left
  • 右节点指针 right
    在这里插入图片描述
顺序存储

顺序存储就是利用数组进行存储,数组中的每一个位置仅存储节点的数据,不存储左右子节点的指针,子节点的索引通过数组下标完成。根结点的序号为 1,对于每个节点 Node,假设它存储在数组中下标为 i 的位置,那么它的左子节点就存储在 2i的位置,它的右子节点存储在下标为 2i+1 的位置。
请添加图片描述
如果数组不是完全二叉树,可以很明显看到浪费了很多存储空间
请添加图片描述

树的遍历

树的遍历分为前序遍历、中序遍历、后序遍历,前序遍历。先中后都是值根节点打印的次序。

先序遍历
先输出根结点,再遍历左子树,最后遍历右子树,遍历左子树和右子树的时候,同样遵循先序遍历的规则,也就是说,可以递归实现先序遍历。

代码如下:

public void preOrder(TreeNode root){
    if(root == null){
        return;
    }
    system.out.println(root.data);
    preOrder(root.left);
    preOrder(root.right);
}

中序遍历
二叉树的中序遍历,就是先递归中序遍历左子树,再输出根结点的值,再递归中序遍历右子树

代码如下:

public void inOrder(TreeNode root){
    if(root == null){
        return;
    }
    inOrder(root.left);
    system.out.println(root.data);
    inOrder(root.right);
}

后序遍历
二叉树的后序遍历,就是先递归后序遍历左子树,再递归后序遍历右子树,最后输出根结点的值

代码如下:

public void postOrder(TreeNode root){
    if(root == null){
        return;
    }
    postOrder(root.left);
    postOrder(root.right);
    system.out.println(root.data);
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值