算法通关村第六关——理解树的结构(青铜)

算法通关村第六关——理解树的结构(青铜)

1. 树的常见概念

树是一种非线性的数据结构,它由若干个节点组成,并且这些节点之间存在特定的关系。在树结构中,每个节点都有一个父节点和零个或多个子节点。

常见概念有如下:

  1. 节点(Node):树中的基本单元,节点通常包含存储数据的数据域和指向其他节点的引用域。
  2. 根节点(Root Node):树的顶层节点,它没有父节点,是整棵树的起点。
  3. 子节点(Child Node):某节点下属于它的直接后继节点。
  4. 父节点(Parent Node):某节点所指向的直接前驱节点。
  5. 叶子节点(Leaf Node):没有任何子节点的节点。
  6. 兄弟节点(Sibling Node):拥有共同父节点的节点。
  7. 子树(Subtree):由一个节点及其所有后代节点组成的树。
  8. 深度(Depth):从根节点到某节点的路径上经过的边数。
  9. 高度(Height):从某节点到它的最远叶子节点的路径上经过的边数。
  10. 层级(Level):根节点的深度为0,它的子节点的深度为1,依次类推。
  11. 祖先节点(Ancestor Node):从根节点到某节点路径上的所有节点。
  12. 后代节点(Descendant Node):某节点下属于它的所有子节点。
  13. 节点的度:一个结点含有的子节点的个数称为该节点的度。
  14. 树的度(Degree):一棵数中,最大的节点的度称为树的度,注意与节点度的区别;
  15. 有序树(Ordered Tree):树中的子节点具有顺序。
  16. 无序树(Unordered Tree):树中的子节点没有特定的顺序。
  17. 森林(Forest):由若干颗互不相交的树组成的集合。

通过一个例子来讲解树的常见概念:

                    高度     深度     层
         A           2       0       1
       /   \
      B     C        1       1       2
    /  \   / \
   D    E F   G      0       2       3

在这个例子中,A是根节点,B和C是A的子节点,D、E、F和G分别是B和C的子节点。叶子节点包括D、E、F和G,它们没有子节点。

以下是树的常见概念的详细解释:

  1. 节点:每个节点都有一个存储数据的数据域(比如字母A、B等)和指向其他节点的引用域。
  2. 根节点:顶层节点A,它没有父节点。
  3. 子节点:B和C是A的子节点,D、E、F和G是B和C的子节点。
  4. 父节点:A是B和C的父节点,B是D和E的父节点,C是F和G的父节点。
  5. 叶子节点:D、E、F和G没有任何子节点。
  6. 兄弟节点:B和C是兄弟节点,也就是拥有共同父节点A的节点。
  7. 深度:根节点A的深度为0,B和C的深度为1,D、E、F和G的深度为2。
  8. 高度:叶子节点D、E、F和G的高度为0,B和C的高度为1,根节点A的高度为2。
  9. 层级:根节点A所在的层级为0,B和C所在的层级为1,D、E、F和G所在的层级为2。
  10. 祖先节点:比如,节点B的祖先节点为A,节点E的祖先节点为B和A。
  11. 后代节点:比如,节点A的后代节点包括B、C、D、E、F和G。

2. 树的性质

树具有以下几个重要的性质:

**性质1:**在二叉树的第i层上至多有2^(i - 1)个节点(i > 0)

**性质2:**深度为k的二叉树至多有2^k - 1 个结点(k>0)

**性质3:**对于任意一棵二叉树,如果其叶结点数为N0,而度数为2的结点总数为N2,则N0=N2+1

**性质4:**具有n个结点的完全二叉树的深度必为log2(n+1)

**性质5:**对完全二叉树,若从上至下、从左至右编号,则编号为i的结点,其左孩子编号必为2i,其右孩子编号必为2i+1;其双亲的编号必为i/2(i = 1 时为根,除外)

让我们以一个家谱树为例来说明这些性质:

        A
       / \
      B   C
     / \   \
    D   E   F
         \
          G

在这个家谱树中,A是根节点,B和C是A的子节点,D、E和F分别是B和C的子节点,G是E的子节点。

  1. 性质1:在二叉树的第i层上至多有2^(i - 1)个节点(i > 0)

    • 第1层上最多有2^(1-1)=1个节点。
    • 第2层上最多有2^(2-1)=2个节点。
    • 第3层上最多有2^(3-1)=4个节点。
  2. 性质2:深度为k的二叉树至多有2^k - 1个结点(k>0)

    • 这棵树的深度为3,所以至多有2^3-1=7个节点。
  3. 性质3:对于任意一棵二叉树,如果其叶结点数为N0,而度数为2的结点总数为N2,则N0=N2+1

    • 叶节点是没有子节点的节点。
    • 度数为2的节点是指具有两个子节点的节点
    • 在这棵树中,叶节点数N0为4(D、G、F),度数为2的节点数N2为2(A、B),满足N0 = N2 + 1。
  4. 性质4:具有n个结点的完全二叉树的深度必为log2(n+1)

    • 这棵树有7个节点,所以它是具有7个节点的完全二叉树,深度为log2(7+1)=3。
  5. 性质5:对完全二叉树,若从上至下、从左至右编号,则编号为i的结点,
    其左孩子编号必为2i,其右孩子编号必为2i+1;其双亲的编号必为i/2(i = 1 时为根,除外)

    • 编号为1的节点A,左孩子编号为2,右孩子编号为3。
    • 编号为2的节点B,左孩子编号为4,右孩子编号为5,双亲编号为1。
    • 编号为3的节点C,右孩子编号为6,双亲编号为1。
    • 编号为4的节点D,没有左孩子和右孩子,双亲编号为2。
    • 编号为5的节点E,左孩子编号为10,右孩子编号为11,双亲编号为2。
    • 编号为6的节点F,没有左孩子和右孩子,双亲编号为3。
    • 编号为7的节点G,没有左孩子和右孩子,双亲编号为5。

3.树的定义与存储方式

定义二叉树

定义树的原理与前面讲的链表本质上是一样的,只不过多了一个指针,如果是二叉树,只要在链表的定义上增加一个指针就可以了

public class BinaryTreeNode {
    private int data; // 节点的数据
    private BinaryTreeNode leftChild; // 左子节点
    private BinaryTreeNode rightChild; // 右子节点
}

本质上就是有两个引用,分别指向两个位置,为了便于理解,我们分别命名为左孩子和右孩子。如果是N叉树该如何定义呢?其实就是每个节点最多可以有N个指针指向其他地方,这是不用left和right,使用一个List就可以了,也就是:

public class NaryTreeNode {
    private int data; // 节点的数据
    private List<NaryTreeNode> children; // 子节点
}

下面给出一个通用的树节点类。它包含了以下属性:

  • id:节点ID,用来唯一标识每个节点。
  • parentId:父节点ID,标识节点的父节点。顶级节点的父节点ID一般为0。
  • label:节点的名称或标签,用来描述节点的内容。
  • children:子节点列表,存储该节点的所有子节点。

通过这个通用的树节点类,可以构建各种类型的树结构,如二叉树、N叉树等。这样的设计可以方便地表示树形结构,并进行相关的操作和遍历。

public class TreeNode {

    /** 节点ID */
    private Integer id;

    /** 父节点ID:顶级节点为0 */
    private Integer parentId;

    /** 节点名称 */
    private String label;

    /** 子节点 */
    private List<TreeNode> children;

    public TreeNode(Integer id, Integer parentId, String label) {
        this.id = id;
        this.parentId = parentId;
        this.label = label;
    }
}

4.树的遍历

二叉树的遍历方式有层次遍历和深度优先遍历两种:

  • 深度优先遍历:先往深走,遇到叶子节点再往回走。
  • 广度优先遍历:一层一层的去遍历,一层访问完再访问下一层。

这两种遍历方式不仅仅是二叉树,N叉树也有这两种方式,图结构也有。

深度优先算法又有前中后序三种。

树的遍历方式主要有三种:前序遍历、中序遍历和后序遍历。下面将结合一个例子来详细讲解这三种遍历方式。

考虑以下二叉树作为例子:

        A
       / \
      B   C
     / \   \
    D   E   F
         \
          G
  1. 前序遍历(Preorder Traversal):按照 根-左-右 的顺序遍历树。
    • 遍历顺序:A -> B -> D -> E -> G -> C -> F
  2. 中序遍历(Inorder Traversal):按照 左-根-右 的顺序遍历树。
    • 遍历顺序:D -> B -> G -> E -> A -> C -> F
  3. 后序遍历(Postorder Traversal):按照 左-右-根 的顺序遍历树。
    • 遍历顺序:D -> G -> E -> B -> F -> C -> A

现在,让我们一步一步地说明如何进行这三种遍历:

  1. 前序遍历:
    • 首先访问根节点A。
    • 然后递归地对左子树进行前序遍历,访问节点B。
    • 继续递归地对左子树进行前序遍历,访问节点D。
    • 左子树遍历完成后,回到B节点,递归地对右子树进行前序遍历,访问节点E。
    • 继续递归地对右子树进行前序遍历,访问节点G。
    • 回到A节点,递归地对右子树进行前序遍历,访问节点C。
    • 最后递归地对右子树进行前序遍历,访问节点F。
  2. 中序遍历:
    • 首先递归地对左子树进行中序遍历,访问节点D。
    • 然后访问根节点B。
    • 继续递归地对左子树进行中序遍历,访问节点E。
    • 继续递归地对右子树进行中序遍历,访问节点G。
    • 回到根节点A,访问它。
    • 递归地对右子树进行中序遍历,访问节点C。
    • 最后递归地对右子树进行中序遍历,访问节点F。
  3. 后序遍历:
    • 首先递归地对左子树进行后序遍历,访问节点D。
    • 继续递归地对左子树进行后序遍历,访问节点G。
    • 然后回到根节点B,递归地对右子树进行后序遍历,访问节点E。
    • 回到根节点A,递归地对右子树进行后序遍历,访问节点C。
    • 继续递归地对右子树进行后序遍历,访问节点F。
    • 最后访问根节点A。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
决策算法是一种广泛应用于分类和回归的机器学习算法,它基于结构对样本进行分类或预测。决策算法的主要思想是通过一系列的判断来对样本进行分类或预测。在决策中,每个节点表示一个属性或特征,每个分支代表该属性或特征的一个取值,而每个叶子节点代表一个分类或预测结果。 决策算法的训练过程主要包括以下步骤: 1. 特征选择:根据某种指标(如信息增益或基尼系数)选择最优的特征作为当前节点的分裂属性。 2. 决策生成:根据选择的特征将数据集分成若干个子集,并递归地生成决策。 3. 剪枝:通过剪枝操作来提高决策的泛化性能。 决策算法的优点包括易于理解和解释、计算复杂度较低、对缺失值不敏感等。但是,决策算法也存在一些缺点,如容易出现过拟合、对离散数据敏感等。 下面是一个决策算法的案例:假设我们要根据一个人的年龄、性别、教育程度和职业预测其收入水平(高于或低于50K)。首先,我们需要将这些特征进行编码,将其转换为数值型数据。然后,我们可以使用决策算法对这些数据进行训练,并生成一个决策模型。最后,我们可以使用该模型对新的数据进行分类或预测。例如,根据一个人的年龄、性别、教育程度和职业,我们可以使用决策模型预测该人的收入水平。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值