一、核心定义与特性
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
}
}
总结
- BST 核心特性:左子树值 < 根值 < 右子树值,中序遍历结果为递增序列;
- 插入逻辑:非递归通过 "父节点 + 循环" 找位置,递归利用 BST 的递归特性简化代码;
- 遍历重点:中序遍历是 BST 的核心遍历方式(有序),前序 / 后序 / 层次遍历各有适用场景,非递归实现需借助栈(DFS)或队列(BFS)。