Whay need Binary Tree

已经有数组、链表了,为什么还需要二叉树?
什么数据结构能在保证顺序的同时,又能快速完成查找、插入和删除呢?
有序数组和哈希表都做不到这一点。
这时就该二叉查找树出场了。

Character

二叉树的特点:

  1. 一棵树有且一个根节点;
  2. 每个节点有且一个上级(根节点除外),两个下级(叫做左子节点,右子节点);
  3. 一个节点的“左”子树中的值都小于节点本身,“右”子树中的值都大于节点本身 , 这个规律贯彻整棵树的所有节点;

二叉树图例:

Implementing with Java:

// 定义一个树节点类
class TreeNode {
    int val; // 节点的值
    TreeNode left; // 左子节点
    TreeNode right; // 右子节点

    // 节点构造函数
    TreeNode(int val) {
        this.val = val;
        this.left = null;
        this.right = null;
    }
}

// 定义二叉树类
public class BinaryTree {
    private TreeNode root; // 二叉树的根节点

    // 二叉树构造函数
    public BinaryTree() {
        root = null;
    }

    // 向二叉树添加节点
    public void add(int val) {
        root = addRecursive(root, val);
    }

    // 递归添加节点
    private TreeNode addRecursive(TreeNode current, int val) {
        if (current == null) {
            return new TreeNode(val);
        }

        if (val < current.val) {
            current.left = addRecursive(current.left, val);
        } else if (val > current.val) {
            current.right = addRecursive(current.right, val);
        } // 如果值已经存在,则不添加

        return current;
    }

    // 在二叉树中查找一个值
    public boolean containsNode(int val) {
        return containsNodeRecursive(root, val);
    }

    // 递归查找值
    private boolean containsNodeRecursive(TreeNode current, int val) {
        if (current == null) {
            return false;
        }
        if (val == current.val) {
            return true;
        }
        return val < current.val
          ? containsNodeRecursive(current.left, val)
          : containsNodeRecursive(current.right, val);
    }

    // 删除二叉树中的节点
    public void delete(int val) {
        root = deleteRecursive(root, val);
    }

    // 递归删除节点
    private TreeNode deleteRecursive(TreeNode current, int val) {
        if (current == null) {
            return null;
        }

        if (val == current.val) {
            // 节点找到,进行删除

            // 情况1: 没有子节点
            if (current.left == null && current.right == null) {
                return null;
            }

            // 情况2: 只有一个子节点
            if (current.right == null) {
                return current.left;
            }

            if (current.left == null) {
                return current.right;
            }

            // 情况3: 有两个子节点
            // 找到右子树中最小的值,用这个值替换要删除的节点,然后删除那个最小的值的节点
            int smallestValue = findSmallestValue(current.right);
            current.val = smallestValue;
            current.right = deleteRecursive(current.right, smallestValue);
            return current;
        } 
        if (val < current.val) {
            current.left = deleteRecursive(current.left, val);
            return current;
        }
        current.right = deleteRecursive(current.right, val);
        return current;
    }

    // 找到最小值(辅助删除操作)
    private int findSmallestValue(TreeNode root) {
        return root.left == null ? root.val : findSmallestValue(root.left);
    }

    // 修改二叉树中的节点,这里的"修改"是删除再添加的方式
    public void update(int oldValue, int newValue) {
        delete(oldValue); // 删除旧值
        add(newValue); // 添加新值
    }

    // 中序遍历打印二叉树
    public void inorderPrint() {
        inorderPrintRecursive(root);
    }

    // 递归中序遍历
    private void inorderPrintRecursive(TreeNode node) {
        if (node != null) {
            inorderPrintRecursive(node.left);
            System.out.print(node.val + " ");
            inorderPrintRecursive(node.right);
        }
    }

    // 主函数,用于测试二叉树的功能
    public static void main(String[] args) {
        BinaryTree tree = new BinaryTree();

        // 添加节点
        tree.add(5);
        tree.add(3);
        tree.add(7);
        tree.add(2);
        tree.add(4);
        tree.add(6);
        tree.add(8);

        // 打印二叉树
        tree.inorderPrint(); // 应输出: 2 3 4 5 6 7 8
        System.out.println();

        // 查找节点
        System.out.println(tree.containsNode(4)); // 应输出: true
        System.out.println(tree.containsNode(9)); // 应输出: false

        // 删除节点
        tree.delete(7);

        // 打印删除节点后的二叉树
        tree.inorderPrint(); // 应输出: 2 3 4 5 6 8
        System.out.println();

        // 修改节点(将5修改为9)
        tree.update(5, 9);

        // 打印修改节点后的二叉树
        tree.inorderPrint(); // 应输出: 2 3 4 6 8 9
    }
}

打印输出:

总结:
二叉搜索树的特性是左子节点的值小于父节点的值,右子节点的值大于父节点的值。这些操作通常采用递归方式实现。

Requirement Scenarios

我之前想使用二叉树去制作一个存储公司员工职级的表(维持上下级关系的层级结构),其实更合适的数据结构可能是多叉树或者类似组织结构的图。在这个结构中,每个节点可以有多个子节点,这代表一个CEO下面有多个经理,经理下有多个下属。

要使用二叉树存储员工信息并查询员工的上级和下级信息,您需要设计一个更复杂的数据结构。二叉树的每个节点将需要存储员工的信息,包括名字和可能的其他信息,比如职位。

标准的二叉搜索树并不适用于这种类型的层级查询,因为它只按一个键(例如员工ID或名字)排序,而不是层级结构。

知道一个数据结构很重要,当遇到一个新业务场景适配什么数据结构也是一门知识。

posted on 2024-01-08 17:13  Mysticbinary  阅读(11)  评论(0编辑  收藏  举报