数据结构与算法-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;
    }
}
相关推荐
A懿轩A5 分钟前
C/C++ 数据结构与算法【数组】 数组详细解析【日常学习,考研必备】带图+详细代码
c语言·数据结构·c++·学习·考研·算法·数组
️南城丶北离1 小时前
[数据结构]图——C++描述
数据结构··最小生成树·最短路径·aov网络·aoe网络
✿ ༺ ོIT技术༻1 小时前
C++11:新特性&右值引用&移动语义
linux·数据结构·c++
suweijie7682 小时前
SpringCloudAlibaba | Sentinel从基础到进阶
java·大数据·sentinel
公贵买其鹿3 小时前
List深拷贝后,数据还是被串改
java
xlsw_6 小时前
java全栈day20--Web后端实战(Mybatis基础2)
java·开发语言·mybatis
神仙别闹7 小时前
基于java的改良版超级玛丽小游戏
java
黄油饼卷咖喱鸡就味增汤拌孜然羊肉炒饭7 小时前
SpringBoot如何实现缓存预热?
java·spring boot·spring·缓存·程序员
暮湫8 小时前
泛型(2)
java
超爱吃士力架8 小时前
邀请逻辑
java·linux·后端