二叉排序树从入门到实践:攻克构建与遍历核心逻辑

一、核心定义与特性

1. 基础定义

二叉排序树(Binary Sort Tree,BST)又称二叉查找树,满足以下规则:

  • 空树是合法的二叉排序树;
  • 非空树中,左子树所有节点值 < 根节点值;
  • 非空树中,右子树所有节点值 > 根节点值;
  • 左、右子树本身也必须是二叉排序树(递归特性)。

2. 核心价值

对 BST 进行中序遍历 ,会得到严格递增的有序序列(这是 BST 最核心的特性,也是其用于数据检索的关键)。

3. 节点类设计(Java)

复制代码
class BSTNode {
    int val; // 节点存储的数据值
    BSTNode left; // 左子节点引用
    BSTNode right; // 右子节点引用

    // 构造方法初始化节点
    public BSTNode(int val) {
        this.val = val;
        this.left = null;
        this.right = null;
    }
}

二、二叉排序树的构建(插入节点)

1. 插入核心逻辑

  • 空树:新节点直接作为根节点;
  • 非空树:从根节点开始,按 "左小右大" 原则循环查找空位置:
    • 新值 < 当前节点值 → 向左子树查找,左子节点为空则插入;
    • 新值 > 当前节点值 → 向右子树查找,右子节点为空则插入;
    • 新值 = 当前节点值 → 跳过(BST 默认不存重复值)。

2. 非递归实现(推荐入门)

复制代码
public class BinarySortTree {
    private BSTNode root; // 根节点

    // 初始化空树
    public BinarySortTree() {
        this.root = null;
    }

    /**
     * 非递归插入节点
     * @param val 要插入的值
     */
    public void insert(int val) {
        BSTNode newNode = new BSTNode(val);
        // 情况1:空树,新节点作为根
        if (root == null) {
            root = newNode;
            return;
        }

        // 情况2:非空树,查找插入位置
        BSTNode curr = root; // 当前遍历节点
        BSTNode parent = null; // 记录父节点(最终插入到父节点的左/右)

        while (curr != null) {
            parent = curr;
            if (val < curr.val) {
                curr = curr.left; // 左子树找
            } else if (val > curr.val) {
                curr = curr.right; // 右子树找
            } else {
                return; // 重复值,直接返回
            }
        }

        // 插入到父节点的左/右
        if (val < parent.val) {
            parent.left = newNode;
        } else {
            parent.right = newNode;
        }
    }
}

3. 递归实现

复制代码
/**
 * 递归插入核心方法(私有,内部调用)
 * @param node 当前遍历节点
 * @param val 要插入的值
 * @return 插入后的当前节点
 */
private BSTNode insertRecursive(BSTNode node, int val) {
    // 递归终止:找到空位置,返回新节点
    if (node == null) {
        return new BSTNode(val);
    }

    // 递归查找左/右子树
    if (val < node.val) {
        node.left = insertRecursive(node.left, val);
    } else if (val > node.val) {
        node.right = insertRecursive(node.right, val);
    }
    // 重复值返回原节点
    return node;
}

// 对外暴露的递归插入方法
public void insertByRecursive(int val) {
    root = insertRecursive(root, val);
}

4. 构建示例

java

运行

复制代码
public static void main(String[] args) {
    int[] arr = {5, 3, 7, 2, 4, 6, 8};
    BinarySortTree bst = new BinarySortTree();
    // 循环插入构建BST
    for (int num : arr) {
        bst.insert(num); // 非递归插入
        // 或 bst.insertByRecursive(num); // 递归插入
    }
}

三、二叉排序树的遍历

1. 深度优先遍历(DFS)

1.1 前序遍历(根 → 左 → 右)
  • 应用:复制树结构、获取拓扑结构;
  • 示例结果(arr={5,3,7,2,4,6,8}):5 3 2 4 7 6 8。

递归实现

复制代码
/**
 * 前序遍历(递归)
 * @param node 当前遍历节点
 */
public void preOrder(BSTNode node) {
    if (node == null) return;
    System.out.print(node.val + " "); // 1. 访问根
    preOrder(node.left); // 2. 遍历左子树
    preOrder(node.right); // 3. 遍历右子树
}

非递归实现(栈)

复制代码
import java.util.Stack;

/**
 * 前序遍历(非递归-栈)
 */
public void preOrderNonRecursive() {
    if (root == null) return;
    Stack<BSTNode> stack = new Stack<>();
    stack.push(root);

    while (!stack.isEmpty()) {
        BSTNode curr = stack.pop();
        System.out.print(curr.val + " "); // 访问根

        // 右子节点先入栈(栈先进后出,保证左先遍历)
        if (curr.right != null) stack.push(curr.right);
        if (curr.left != null) stack.push(curr.left);
    }
}
1.2 中序遍历(左 → 根 → 右)
  • 核心优势:遍历结果为递增有序序列;
  • 应用:获取有序数据、验证 BST 合法性;
  • 示例结果:2 3 4 5 6 7 8。

递归实现

复制代码
/**
 * 中序遍历(递归)
 * @param node 当前遍历节点
 */
public void inOrder(BSTNode node) {
    if (node == null) return;
    inOrder(node.left); // 1. 遍历左子树
    System.out.print(node.val + " "); // 2. 访问根
    inOrder(node.right); // 3. 遍历右子树
}

非递归实现(栈)

复制代码
/**
 * 中序遍历(非递归-栈)
 */
public void inOrderNonRecursive() {
    if (root == null) return;
    Stack<BSTNode> stack = new Stack<>();
    BSTNode curr = root;

    while (curr != null || !stack.isEmpty()) {
        // 先把所有左子节点压栈
        while (curr != null) {
            stack.push(curr);
            curr = curr.left;
        }
        // 弹出栈顶,访问并遍历右子树
        curr = stack.pop();
        System.out.print(curr.val + " ");
        curr = curr.right;
    }
}
1.3 后序遍历(左 → 右 → 根)
  • 应用:删除树结构、计算子树节点数 / 深度;
  • 示例结果:2 4 3 6 8 7 5。

递归实现

复制代码
/**
 * 后序遍历(递归)
 * @param node 当前遍历节点
 */
public void postOrder(BSTNode node) {
    if (node == null) return;
    postOrder(node.left); // 1. 遍历左子树
    postOrder(node.right); // 2. 遍历右子树
    System.out.print(node.val + " "); // 3. 访问根
}

2. 广度优先遍历(BFS):层次遍历

  • 逻辑:按层级访问(根→第二层→第三层...);

  • 实现:借助队列(先进先出);

  • 应用:按层级处理任务、计算树的宽度;

  • 示例结果:5 3 7 2 4 6 8。

    import java.util.LinkedList;
    import java.util.Queue;

    /**

    • 层次遍历(队列实现)
      */
      public void levelOrder() {
      if (root == null) return;
      Queue<BSTNode> queue = new LinkedList<>();
      queue.offer(root); // 根节点入队

      while (!queue.isEmpty()) {
      BSTNode curr = queue.poll(); // 出队并访问
      System.out.print(curr.val + " ");

      复制代码
       // 左子节点先入队,保证层级顺序
       if (curr.left != null) queue.offer(curr.left);
       if (curr.right != null) queue.offer(curr.right);

      }
      }

四、完整测试代码

复制代码
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;

// 节点类
class BSTNode {
    int val;
    BSTNode left;
    BSTNode right;

    public BSTNode(int val) {
        this.val = val;
        this.left = null;
        this.right = null;
    }
}

// 二叉排序树操作类
public class BinarySortTree {
    private BSTNode root;

    public BinarySortTree() {
        this.root = null;
    }

    // 非递归插入
    public void insert(int val) {
        BSTNode newNode = new BSTNode(val);
        if (root == null) {
            root = newNode;
            return;
        }
        BSTNode curr = root;
        BSTNode parent = null;
        while (curr != null) {
            parent = curr;
            if (val < curr.val) {
                curr = curr.left;
            } else if (val > curr.val) {
                curr = curr.right;
            } else {
                return;
            }
        }
        if (val < parent.val) {
            parent.left = newNode;
        } else {
            parent.right = newNode;
        }
    }

    // 递归插入
    private BSTNode insertRecursive(BSTNode node, int val) {
        if (node == null) {
            return new BSTNode(val);
        }
        if (val < node.val) {
            node.left = insertRecursive(node.left, val);
        } else if (val > node.val) {
            node.right = insertRecursive(node.right, val);
        }
        return node;
    }

    public void insertByRecursive(int val) {
        root = insertRecursive(root, val);
    }

    // 前序遍历(递归)
    public void preOrder(BSTNode node) {
        if (node == null) return;
        System.out.print(node.val + " ");
        preOrder(node.left);
        preOrder(node.right);
    }

    // 前序遍历(非递归)
    public void preOrderNonRecursive() {
        if (root == null) return;
        Stack<BSTNode> stack = new Stack<>();
        stack.push(root);
        while (!stack.isEmpty()) {
            BSTNode curr = stack.pop();
            System.out.print(curr.val + " ");
            if (curr.right != null) stack.push(curr.right);
            if (curr.left != null) stack.push(curr.left);
        }
    }

    // 中序遍历(递归)
    public void inOrder(BSTNode node) {
        if (node == null) return;
        inOrder(node.left);
        System.out.print(node.val + " ");
        inOrder(node.right);
    }

    // 中序遍历(非递归)
    public void inOrderNonRecursive() {
        if (root == null) return;
        Stack<BSTNode> stack = new Stack<>();
        BSTNode curr = root;
        while (curr != null || !stack.isEmpty()) {
            while (curr != null) {
                stack.push(curr);
                curr = curr.left;
            }
            curr = stack.pop();
            System.out.print(curr.val + " ");
            curr = curr.right;
        }
    }

    // 后序遍历(递归)
    public void postOrder(BSTNode node) {
        if (node == null) return;
        postOrder(node.left);
        postOrder(node.right);
        System.out.print(node.val + " ");
    }

    // 层次遍历
    public void levelOrder() {
        if (root == null) return;
        Queue<BSTNode> queue = new LinkedList<>();
        queue.offer(root);
        while (!queue.isEmpty()) {
            BSTNode curr = queue.poll();
            System.out.print(curr.val + " ");
            if (curr.left != null) queue.offer(curr.left);
            if (curr.right != null) queue.offer(curr.right);
        }
    }

    // 获取根节点(供遍历调用)
    public BSTNode getRoot() {
        return root;
    }

    // 测试主方法
    public static void main(String[] args) {
        int[] arr = {5, 3, 7, 2, 4, 6, 8};
        BinarySortTree bst = new BinarySortTree();
        for (int num : arr) {
            bst.insert(num);
        }

        System.out.println("前序遍历(递归):");
        bst.preOrder(bst.getRoot()); // 5 3 2 4 7 6 8
        System.out.println("\n前序遍历(非递归):");
        bst.preOrderNonRecursive();
        System.out.println("\n中序遍历(递归):");
        bst.inOrder(bst.getRoot()); // 2 3 4 5 6 7 8
        System.out.println("\n中序遍历(非递归):");
        bst.inOrderNonRecursive();
        System.out.println("\n后序遍历(递归):");
        bst.postOrder(bst.getRoot()); // 2 4 3 6 8 7 5
        System.out.println("\n层次遍历:");
        bst.levelOrder(); // 5 3 7 2 4 6 8
    }
}

总结

  1. BST 核心特性:左子树值 < 根值 < 右子树值,中序遍历结果为递增序列;
  2. 插入逻辑:非递归通过 "父节点 + 循环" 找位置,递归利用 BST 的递归特性简化代码;
  3. 遍历重点:中序遍历是 BST 的核心遍历方式(有序),前序 / 后序 / 层次遍历各有适用场景,非递归实现需借助栈(DFS)或队列(BFS)。
相关推荐
技术小甜甜1 小时前
[Python实战] 用 pathlib 彻底统一文件路径处理,比字符串拼接稳得多
开发语言·人工智能·python·ai·效率化
xyq20241 小时前
jQuery Mobile 按钮:深度解析与最佳实践
开发语言
fpcc1 小时前
跟我学C++中级篇—std::shared_ptr的线程安全性分析
开发语言·c++
wayz112 小时前
正则表达式:从入门到精通
java·python·正则表达式·编辑器
bbq粉刷匠2 小时前
Java--多线程--线程安全3
java·开发语言
2401_831920742 小时前
C++中的桥接模式
开发语言·c++·算法
Promising_GEO2 小时前
探索Python融合地学:绘制栅格数据经纬度剖面图
开发语言·python·遥感·地理
m0_743470372 小时前
C++中的桥接模式变体
开发语言·c++·算法
IT猿手2 小时前
MATLAB画四旋翼无人机,机翼可独立旋转
开发语言·matlab·无人机