数据结构与算法-10高级数据结构_树论(树论基础)

树论基础&二叉树

1 什么是树

概念

  • 数据结构中的"树"(Tree)是一种非常重要的非线性数据结构,它模拟了具有树状结构特点的数据集合。在树形结构中,每个元素被称为一个节点(Node),节点之间通过特定的关系连接,这些关系通常被描述为"父子"关系。

  • 树是由n(n≥0)个有限节点组成一个具有层次关系的集合。它有一个特殊的节点,称为根节点(Root Node),其余节点分成m(m≥0)个互不相交的有限集T1, T2, ..., Tm,其中每一个子集Ti(1≤i≤m)又是一棵符合本定义的树,称为根的子树(Subtree)

特性

  1. 层次性:树中的节点按照层次组织,根节点位于最顶层,叶子节点位于最底层。
  2. 无环性:在树中,除了根节点外,每个节点有且仅有一个父节点;没有节点是其自身的祖先或后代。
  3. 子树不相交性:任意两个子树的节点之间没有交集。

2 重要术语

  1. 节点 (Node)
    • 树的每个元素都是一个节点。
    • 节点可能包含一个值或一组值,以及指向其子节点的链接。
  2. 根节点 (Root Node)
    • 树中唯一没有父节点的节点。
    • 它通常是树的入口点。
  3. 子节点 (Child Node)
    • 一个节点可以有零个或多个子节点。
    • 子节点通过边(Edge)与父节点相连。
  4. 父节点 (Parent Node)
    • 子节点的上一级节点。
    • 除了根节点外,每个节点都有一个父节点。
  5. 兄弟节点 (Sibling Nodes)
    • 具有相同父节点的节点。
  6. 叶子节点 (Leaf Node)
    • 没有子节点的节点。
    • 它们位于树的最低层
  7. (Degree)
    • 一个节点的子节点数。
    • 叶子节点的度为0。
    • 示例:在二叉树中,每个节点最多有两个子节点(一个左子节点和一个右子节点),因此二叉树中节点的度最大为2。但在一般的树(也称为N叉树)中,节点的度可以大于2,具体取决于树的定义和上下文。
  8. 树的度 (Degree of a Tree)
    • 树中所有节点的度的最大值。
  9. 层次 (Level)
    • 从根节点开始,根节点为第1层,它的子节点为第2层,依此类推。
  10. 深度 (Depth)或高度 (Height)
    • 树中节点的最大层次数。
    • 根节点的深度为0,其直接子节点的深度为1,依此类推。
  11. 路径 (Path)
    • 从一个节点到另一个节点所经过的节点序列。
    • 路径长度是路径上的节点数减一。
  12. 森林 (Forest)
    • 一个或多个互不相交的树的集合。
  13. 结点的高度:结点到叶子结点的最长路径
  14. 结点的深度:根结点到该结点的边个数
  15. 结点的层数:结点的深度加1
  16. 树的高度:根结点的高度

3 不同的树

  1. 二叉树 :每个节点最多有两个子节点的树。
    1. 每个节点最多有两个子节点,通常称为左子节点和右子节点。
    2. 子树之间不能相交。
    3. 除了根节点外,每个节点有且仅有一个父节点。
    4. 一颗N个结点的树有N-1条边。
    5. 一个节点的子树的个数称为节点的度,普通二叉树中节点的度最大为2。
  2. 二叉搜索树(BST):二叉树的一种特殊形式,其中对于树中的每个节点,其左子树上所有节点的值都小于它的值,而右子树上所有节点的值都大于它的值。
  3. 平衡二叉树:一种特殊的二叉搜索树,其中任意节点的两个子树的高度差最多为1。常见的平衡二叉树有AVL树和红黑树。
  4. 完全二叉树 :除最后一层外,每一层上的节点数均达到最大值;在最后一层上只缺少右边的若干节点。
    1. 编号性质:对于深度为h的完全二叉树,它的节点从1到2^h-1依次编号。其中,对于任意节点i,如果它的编号为i,则它的左子节点编号为2i,右子节点编号为2i+1。
    2. 父子关系:对于任意节点i,如果它的编号为i,则它的父节点编号为i/2(向下取整)。
    3. 高度:完全二叉树的高度为log(n+1)(以2为底),其中n为节点数。
    4. 存储方式:完全二叉树可以使用数组来存储,从而实现快速的访问和修改。
  5. 满二叉树 :除叶子结点外,每个结点都有左右两个子结点。
    1. 每一层的节点数都达到了最大值。
    2. 节点要么是叶子节点(没有子节点),要么是度为2的节点(有两个子节点)。
  6. N叉树:每个节点可以有N个子节点的树,其中N是一个大于1的整数。
  7. B树和B+树:用于数据库和文件系统的平衡多路搜索树,它们允许每个节点有多个子节点和关键字,用于高效地插入、删除和搜索数据。
  8. 堆(Heap):一种特殊的树形数据结构,通常用于实现优先队列。堆是一种完全二叉树,它满足堆的性质:父节点的值总是大于或等于(大顶堆)或小于或等于(小顶堆)其子节点的值。

4 二叉树的遍历

4.1 前序遍历

前序遍历顺序:根节点、左节点、右节点

JAVA 复制代码
/**
* 前序遍历
* @param node
*/
public void preOrder(MyBinaryTreeNode<T> node){
    print(node);
    if (node.left != null){
        preOrder(node.left);
    }
    if (node.right != null){
        preOrder(node.right);
    }
}
4.2 中序遍历

中序遍历顺序:左节点、跟节点、右节点

JAVA 复制代码
/**
* 中序遍历
*/
public void middleOrder(MyBinaryTreeNode<T> node){
    if (node == null){
        return;
    }
    if (node.left != null){
        middleOrder(node.left);
    }
    print(node);
    if (node.right != null){
        middleOrder(node.right);
    }
}
4.3 后续遍历

后续遍历顺序:左节点、右节点、根节点

JAVA 复制代码
/**
 * 后续遍历
*/
public void postOrder(MyBinaryTreeNode<T> node){
    if (node == null){
        return;
    }
    if (node.left != null){
        postOrder(node.left);
    }
    if (node.right != null){
        postOrder(node.right);
    }
    print(node);
}
4.4 层次遍历

层次遍历:也叫横向遍历

java 复制代码
/**
* 层级遍历
*/
public void transverseSort(MyBinaryTreeNode<T> node){
    if (node == null){
        return;
    }
    print(node);
    ArrayQueue<MyBinaryTreeNode<T>> queue = new ArrayQueue<>(10);
    queue.add(node);
    while (!queue.isEmpty()){
        MyBinaryTreeNode<T> remove = queue.remove(0);
        if (remove.left != null){
            print(remove.left);
            queue.add(remove.left);
        }
        if (remove.right != null){
            print(remove.right);
            queue.add(remove.right);
        }
    }
}
4.5 完整代码
JAVA 复制代码
package cn.zxc.demo.leetcode_demo.advanced_data_structure;

import com.sun.jmx.remote.internal.ArrayQueue;

/**
 * 二叉树
 *              A
 *            /   \
 *           B     E
 *            \     \
 *            C      F
 *           /      /
 *          D      G
 *               /  \
 *              H    K
 * 前序遍历:
 * A B C D E F G H K
 * 中序遍历:
 * B D C A E H G K F
 * 后序遍历:
 * D C B H K G F E A
 * 层级遍历:
 * A B E C F D G H K
 */
public class MyBinaryTreeDemo<T> {


    /**
     * 前序遍历
     * @param node
     */
    public void preOrder(MyBinaryTreeNode<T> node){
        print(node);
        if (node.left != null){
            preOrder(node.left);
        }
        if (node.right != null){
            preOrder(node.right);
        }
    }

    /**
     * 中序遍历
     */
    public void middleOrder(MyBinaryTreeNode<T> node){
        if (node == null){
            return;
        }
        if (node.left != null){
            middleOrder(node.left);
        }
        print(node);
        if (node.right != null){
            middleOrder(node.right);
        }
    }

    /**
     * 后续遍历
     */
    public void postOrder(MyBinaryTreeNode<T> node){
        if (node == null){
            return;
        }
        if (node.left != null){
            postOrder(node.left);
        }
        if (node.right != null){
            postOrder(node.right);
        }
        print(node);
    }

    /**
     * 层级遍历
     */
    public void transverseSort(MyBinaryTreeNode<T> node){
        if (node == null){
            return;
        }
        print(node);
        ArrayQueue<MyBinaryTreeNode<T>> queue = new ArrayQueue<>(10);
        queue.add(node);
        while (!queue.isEmpty()){
            MyBinaryTreeNode<T> remove = queue.remove(0);
            if (remove.left != null){
                print(remove.left);
                queue.add(remove.left);
            }
            if (remove.right != null){
                print(remove.right);
                queue.add(remove.right);
            }
        }
    }

    /**
     * 打印
     * @param node
     */
    public void print(MyBinaryTreeNode<T> node){
        if(node == null){
            return;
        }
        System.out.print(node.data + " ");
    }

    public static void main(String[] args) {
        MyBinaryTreeNode<String> D = new MyBinaryTreeNode<String>("D", null, null);
        MyBinaryTreeNode<String> H = new MyBinaryTreeNode<String>("H", null, null);
        MyBinaryTreeNode<String> K = new MyBinaryTreeNode<String>("K", null, null);
        MyBinaryTreeNode<String> C = new MyBinaryTreeNode<String>("C", D, null);
        MyBinaryTreeNode<String> G = new MyBinaryTreeNode<String>("G", H, K);
        MyBinaryTreeNode<String> B = new MyBinaryTreeNode<String>("B", null, C);
        MyBinaryTreeNode<String> F = new MyBinaryTreeNode<String>("F", G, null);
        MyBinaryTreeNode<String> E = new MyBinaryTreeNode<String>("E", null, F);
        MyBinaryTreeNode<String> A = new MyBinaryTreeNode<String>("A", B, E);
        MyBinaryTreeDemo<String> myBinaryTreeDemo = new MyBinaryTreeDemo<>();
        System.out.println("前序遍历:");
        myBinaryTreeDemo.preOrder(A); // A B C D E F G H K
        System.out.println();
        System.out.println("中序遍历:"); // B D C A E H G K F
        myBinaryTreeDemo.middleOrder(A);
        System.out.println();
        System.out.println("后序遍历:"); // D C B H K G F E A
        myBinaryTreeDemo.postOrder(A);
        System.out.println();
        System.out.println("层级遍历:");
        myBinaryTreeDemo.transverseSort(A);
        System.out.println();
    }
}
class MyBinaryTreeNode<T> {
    T data;
    MyBinaryTreeNode<T> left;
    MyBinaryTreeNode<T> right;
    public MyBinaryTreeNode(T data) {
        this.data = data;
    }
    public MyBinaryTreeNode(T data, MyBinaryTreeNode<T> left, MyBinaryTreeNode<T> right) {
        this.data = data;
        this.left = left;
        this.right = right;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public MyBinaryTreeNode<T> getLeft() {
        return left;
    }

    public void setLeft(MyBinaryTreeNode<T> left) {
        this.left = left;
    }

    public MyBinaryTreeNode<T> getRight() {
        return right;
    }

    public void setRight(MyBinaryTreeNode<T> right) {
        this.right = right;
    }
}
相关推荐
考虑考虑1 天前
Jpa使用union all
java·spring boot·后端
用户3721574261351 天前
Java 实现 Excel 与 TXT 文本高效互转
java
浮游本尊1 天前
Java学习第22天 - 云原生与容器化
java
渣哥1 天前
原来 Java 里线程安全集合有这么多种
java
间彧1 天前
Spring Boot集成Spring Security完整指南
java
间彧1 天前
Spring Secutiy基本原理及工作流程
java
Java水解1 天前
JAVA经典面试题附答案(持续更新版)
java·后端·面试
洛小豆1 天前
在Java中,Integer.parseInt和Integer.valueOf有什么区别
java·后端·面试
前端小张同学1 天前
服务器上如何搭建jenkins 服务CI/CD😎😎
java·后端
ytadpole1 天前
Spring Cloud Gateway:一次不规范 URL 引发的路由转发404问题排查
java·后端