树的常见算法及Java实现

一、常见树的类型及应用

树类型 (Tree Type) 主要特点 (Key Characteristics) 经典应用场景 (Typical Use Cases) 涉及的重要算法 (Related Algorithms)
二叉树 (Binary Tree) 每个节点最多有两个子节点(左子树、右子树)。结构自由,没有严格平衡规则。 作为其他复杂树结构的基础;用于表达数学表达式(表达式树)。 树的遍历(前序、中序、后序、层序)。
二叉搜索树 (BST - Binary Search Tree) 在二叉树基础上,满足:左子树上所有节点的值 < 根节点的值 < 右子树上所有节点的值。 用于快速查找、插入、删除数据,理想情况下时间复杂度为 O(log n)。 查找、插入、删除。
平衡二叉搜索树 (Balanced BST) 1. AVL 树 通过旋转操作严格保持平衡(任意节点的左右子树高度差绝对值不超过1)。查找效率极高。 2. 红黑树 (Red-Black Tree) 通过着色和旋转规则保持近似平衡(从根到叶子的最长路径不超过最短路径的2倍)。插入删除效率更高,统计性能更优。 AVL 树 :适用于大量查询 操作而插入删除相对较少的场景,如数据库索引。 红黑树 :广泛应用于需要高效插入删除的场景,如: - Java中的 HashMap(冲突链表超过阈值转红黑树) - C++ STL 中的 map, set - Linux 进程调度 旋转 (Rotations) :左旋、右旋。 AVL :计算平衡因子并进行调整。 红黑树:节点变色和旋转以满足五大性质。
B 树 (B-Tree) 多路 平衡搜索树,一个节点可以有多个key和多个子节点。节点大小通常等于一个磁盘页,大大减少磁盘I/O次数 数据库索引文件系统 (如NTFS, ReiserFS)的核心数据结构。专门为处理海量数据和外存(磁盘)存储而设计。 分裂(Split)、合并(Merge)、查找、插入、删除。
B+ 树 (B+ Tree) B树的变体,所有数据记录都存储在叶子节点,且叶子节点之间通过指针相连形成有序链表。非叶子节点仅存放键(索引)。 比B树更广泛应用于数据库索引 (如MySQL InnoDB)和操作系统的文件索引 。原因: 1. 查询效率更稳定(任何查找都要到叶子节点)。 2. 范围查询和全表扫描效率极高(通过叶子节点链表)。 分裂、合并、查找、插入、删除。
字典树 (Trie) 又名前缀树,专门用于处理字符串。节点的位置决定了其代表的字符串(从根到该节点的路径)。 - 搜索引擎的自动补全/提示 - 输入法联想 - IP路由表的最长前缀匹配 - 统计和排序大量字符串 插入字符串、搜索前缀/完整字符串、深度优先遍历收集所有单词。
堆 (Heap) 一种特殊的完全二叉树,满足堆属性:父节点的值总是 >=(最大堆)或 <=(最小堆)所有子节点的值。不是搜索树,无法快速查找任意值。 - 优先队列 (Priority Queue)的实现 - 堆排序 (Heap Sort) - 求Top K问题 - 图算法中的Dijkstra算法 上浮 (Sift Up / Percolate Up) 下沉 (Sift Down / Heapify) 建堆(Heapify)
线段树 (Segment Tree) 一种用于处理区间/段查询的二叉树结构。每个节点代表一个区间,并存储该区间的聚合信息(如 sum, min, max)。 - 区间求和、求最值 - 区间更新 (如给区间内所有值加上一个数) - 统计类、范围类问题 建树 (Build) 区间查询 (Query / Range Query) 区间更新 (Update / Range Update) (常用懒惰传播 Lazy Propagation 优化)
哈夫曼树 (Huffman Tree) 一种带权路径长度最短的最优二叉树自底向上构建,频率越高的字符离根越近,编码越短。 数据压缩 (如GZIP, JPEG, MP3等编码的基础算法),用于构建前缀编码,即哈夫曼编码。 构建哈夫曼树生成哈夫曼编码
  • 需要快速查找、插入、删除(通用) :首选红黑树,它在实践中综合性能最好。

  • 海量数据,涉及磁盘存储(如数据库) :选择B+树,它最大限度地减少了磁盘访问次数。

  • 处理字符串和前缀相关的问题 :选择字典树 (Trie)

  • 需要管理优先级的任务调度 :选择来实现优先队列。

  • 频繁进行区间统计和更新 :选择线段树

  • 目标是为了数据压缩 :使用哈夫曼树构建编码。

二、树的遍历算法与构建

二叉树的基本节点结构:

java 复制代码
class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    
    TreeNode(int val) {
        this.val = val;
        this.left = null;
        this.right = null;
    }
}

2.1 树的深度优先遍历(DFS)

2.1.1 前序遍历 (根-左-右)

java 复制代码
// 递归实现
public void preorderTraversal(TreeNode root) {
    if (root == null) return;
    System.out.print(root.val + " ");
    preorderTraversal(root.left);
    preorderTraversal(root.right);
}

// 迭代实现
public void preorderTraversalIterative(TreeNode root) {
    if (root == null) return;
    Stack<TreeNode> stack = new Stack<>();
    stack.push(root);
    
    while (!stack.isEmpty()) {
        TreeNode node = stack.pop();
        System.out.print(node.val + " ");
        
        if (node.right != null) stack.push(node.right);
        if (node.left != null) stack.push(node.left);
    }
}

2.1.2 中序遍历 (左-根-右)

java 复制代码
// 递归实现
public void inorderTraversal(TreeNode root) {
    if (root == null) return;
    inorderTraversal(root.left);
    System.out.print(root.val + " ");
    inorderTraversal(root.right);
}

// 迭代实现
public void inorderTraversalIterative(TreeNode root) {
    Stack<TreeNode> stack = new Stack<>();
    TreeNode 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;
    }
}

2.1.3 后序遍历 (左-右-根)

java 复制代码
// 递归实现
public void postorderTraversal(TreeNode root) {
    if (root == null) return;
    postorderTraversal(root.left);
    postorderTraversal(root.right);
    System.out.print(root.val + " ");
}

// 迭代实现
public void postorderTraversalIterative(TreeNode root) {
    if (root == null) return;
    
    Stack<TreeNode> stack = new Stack<>();
    Stack<TreeNode> output = new Stack<>();
    stack.push(root);
    
    while (!stack.isEmpty()) {
        TreeNode node = stack.pop();
        output.push(node);
        
        if (node.left != null) stack.push(node.left);
        if (node.right != null) stack.push(node.right);
    }
    
    while (!output.isEmpty()) {
        System.out.print(output.pop().val + " ");
    }
}

2.2 广度优先遍历 (BFS/层次遍历)

java 复制代码
public void levelOrderTraversal(TreeNode root) {
    if (root == null) return;
    
    Queue<TreeNode> queue = new LinkedList<>();
    queue.offer(root);
    
    while (!queue.isEmpty()) {
        TreeNode node = queue.poll();
        System.out.print(node.val + " ");
        
        if (node.left != null) queue.offer(node.left);
        if (node.right != null) queue.offer(node.right);
    }
}

2.3 树的构建

2.3.1 从前序和中序遍历构建二叉树

java 复制代码
public class PreInOrderBuilder {
    private Map<Integer, Integer> inOrderMap;
    private int preIndex;
    
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        if (preorder == null || inorder == null || preorder.length != inorder.length) {
            return null;
        }
        
        // 创建中序遍历值到索引的映射
        inOrderMap = new HashMap<>();
        for (int i = 0; i < inorder.length; i++) {
            inOrderMap.put(inorder[i], i);
        }
        
        preIndex = 0;
        return buildTreeHelper(preorder, 0, inorder.length - 1);
    }
    
    private TreeNode buildTreeHelper(int[] preorder, int inStart, int inEnd) {
        if (inStart > inEnd) {
            return null;
        }
        
        // 前序遍历的第一个元素是根节点
        int rootVal = preorder[preIndex++];
        TreeNode root = new TreeNode(rootVal);
        
        // 在中序遍历中找到根节点的位置
        int inIndex = inOrderMap.get(rootVal);
        
        // 递归构建左子树和右子树
        root.left = buildTreeHelper(preorder, inStart, inIndex - 1);
        root.right = buildTreeHelper(preorder, inIndex + 1, inEnd);
        
        return root;
    }
}

2.3.2 从中序和后序遍历构建二叉树

java 复制代码
public class InPostOrderBuilder {
    private Map<Integer, Integer> inOrderMap;
    private int postIndex;
    
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        if (inorder == null || postorder == null || inorder.length != postorder.length) {
            return null;
        }
        
        // 创建中序遍历值到索引的映射
        inOrderMap = new HashMap<>();
        for (int i = 0; i < inorder.length; i++) {
            inOrderMap.put(inorder[i], i);
        }
        
        postIndex = postorder.length - 1;
        return buildTreeHelper(postorder, 0, inorder.length - 1);
    }
    
    private TreeNode buildTreeHelper(int[] postorder, int inStart, int inEnd) {
        if (inStart > inEnd) {
            return null;
        }
        
        // 后序遍历的最后一个元素是根节点
        int rootVal = postorder[postIndex--];
        TreeNode root = new TreeNode(rootVal);
        
        // 在中序遍历中找到根节点的位置
        int inIndex = inOrderMap.get(rootVal);
        
        // 注意:需要先构建右子树,再构建左子树
        root.right = buildTreeHelper(postorder, inIndex + 1, inEnd);
        root.left = buildTreeHelper(postorder, inStart, inIndex - 1);
        
        return root;
    }
}

2.3.3 从前序和后序遍历构建二叉树(不唯一,需附加条件)

java 复制代码
public class PrePostOrderBuilder {
    private Map<Integer, Integer> postOrderMap;
    private int preIndex;
    
    // 注意:前序+后序不能唯一确定二叉树,需要附加条件
    // 这里假设树是真二叉树(每个节点有0或2个子节点)
    public TreeNode buildTree(int[] preorder, int[] postorder) {
        if (preorder == null || postorder == null || preorder.length != postorder.length) {
            return null;
        }
        
        // 创建后序遍历值到索引的映射
        postOrderMap = new HashMap<>();
        for (int i = 0; i < postorder.length; i++) {
            postOrderMap.put(postorder[i], i);
        }
        
        preIndex = 0;
        return buildTreeHelper(preorder, 0, postorder.length - 1);
    }
    
    private TreeNode buildTreeHelper(int[] preorder, int postStart, int postEnd) {
        if (postStart > postEnd) {
            return null;
        }
        
        if (preIndex >= preorder.length) {
            return null;
        }
        
        // 前序遍历的第一个元素是根节点
        int rootVal = preorder[preIndex++];
        TreeNode root = new TreeNode(rootVal);
        
        if (postStart == postEnd) {
            return root;
        }
        
        // 找到左子树的根节点在后序遍历中的位置
        int leftRootVal = preorder[preIndex];
        int leftRootIndex = postOrderMap.get(leftRootVal);
        
        // 递归构建左子树和右子树
        if (leftRootIndex <= postEnd - 1) {
            root.left = buildTreeHelper(preorder, postStart, leftRootIndex);
            root.right = buildTreeHelper(preorder, leftRootIndex + 1, postEnd - 1);
        }
        
        return root;
    }
}

2.3.4 从层次和中序遍历构建二叉树

java 复制代码
public class LevelInOrderBuilder {
    private Map<Integer, Integer> inOrderMap;
    
    public TreeNode buildTree(int[] levelOrder, int[] inOrder) {
        if (levelOrder == null || inOrder == null || levelOrder.length != inOrder.length) {
            return null;
        }
        
        // 创建中序遍历值到索引的映射
        inOrderMap = new HashMap<>();
        for (int i = 0; i < inOrder.length; i++) {
            inOrderMap.put(inOrder[i], i);
        }
        
        return buildTreeHelper(levelOrder, 0, inOrder.length - 1);
    }
    
    private TreeNode buildTreeHelper(int[] levelOrder, int inStart, int inEnd) {
        if (inStart > inEnd) {
            return null;
        }
        
        if (levelOrder.length == 0) {
            return null;
        }
        
        // 找到当前层次遍历中第一个出现在中序遍历区间[inStart, inEnd]中的元素
        TreeNode root = null;
        int rootIndexInLevel = -1;
        
        for (int i = 0; i < levelOrder.length; i++) {
            int val = levelOrder[i];
            if (inOrderMap.get(val) >= inStart && inOrderMap.get(val) <= inEnd) {
                root = new TreeNode(val);
                rootIndexInLevel = i;
                break;
            }
        }
        
        if (root == null) {
            return null;
        }
        
        int rootIndexInInorder = inOrderMap.get(root.val);
        
        // 提取左子树和右子树的层次遍历序列
        int[] leftLevel = extractLevelOrder(levelOrder, rootIndexInLevel, inStart, rootIndexInInorder - 1);
        int[] rightLevel = extractLevelOrder(levelOrder, rootIndexInLevel, rootIndexInInorder + 1, inEnd);
        
        // 递归构建左子树和右子树
        root.left = buildTreeHelper(leftLevel, inStart, rootIndexInInorder - 1);
        root.right = buildTreeHelper(rightLevel, rootIndexInInorder + 1, inEnd);
        
        return root;
    }
    
    private int[] extractLevelOrder(int[] levelOrder, int rootIndex, int inStart, int inEnd) {
        if (inStart > inEnd) {
            return new int[0];
        }
        
        List<Integer> result = new ArrayList<>();
        for (int i = 0; i < levelOrder.length; i++) {
            if (i == rootIndex) continue; // 跳过根节点
            
            int val = levelOrder[i];
            int indexInInorder = inOrderMap.get(val);
            
            if (indexInInorder >= inStart && indexInInorder <= inEnd) {
                result.add(val);
            }
        }
        
        // 转换为数组
        int[] arr = new int[result.size()];
        for (int i = 0; i < result.size(); i++) {
            arr[i] = result.get(i);
        }
        return arr;
    }
}

三、常见树算法

3.1 计算树的高度/深度

java 复制代码
public int maxDepth(TreeNode root) {
    if (root == null) return 0;
    return 1 + Math.max(maxDepth(root.left), maxDepth(root.right));
}

3.2 判断对称二叉树

java 复制代码
public boolean isSymmetric(TreeNode root) {
    if (root == null) return true;
    return isMirror(root.left, root.right);
}

private boolean isMirror(TreeNode t1, TreeNode t2) {
    if (t1 == null && t2 == null) return true;
    if (t1 == null || t2 == null) return false;
    return (t1.val == t2.val) 
        && isMirror(t1.left, t2.right) 
        && isMirror(t1.right, t2.left);
}

3.2 判断平衡二叉树

java 复制代码
public boolean isBalanced(TreeNode root) {
    return checkHeight(root) != -1;
}

private int checkHeight(TreeNode root) {
    if (root == null) return 0;
    
    int leftHeight = checkHeight(root.left);
    if (leftHeight == -1) return -1;
    
    int rightHeight = checkHeight(root.right);
    if (rightHeight == -1) return -1;
    
    if (Math.abs(leftHeight - rightHeight) > 1) return -1;
    
    return 1 + Math.max(leftHeight, rightHeight);
}

3.3 二叉搜索树验证

java 复制代码
public boolean isValidBST(TreeNode root) {
    return isValidBST(root, Long.MIN_VALUE, Long.MAX_VALUE);
}

private boolean isValidBST(TreeNode node, long min, long max) {
    if (node == null) return true;
    if (node.val <= min || node.val >= max) return false;
    return isValidBST(node.left, min, node.val) 
        && isValidBST(node.right, node.val, max);
}

3.4 最近公共祖先 (LCA)

java 复制代码
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
    if (root == null || root == p || root == q) return root;
    
    TreeNode left = lowestCommonAncestor(root.left, p, q);
    TreeNode right = lowestCommonAncestor(root.right, p, q);
    
    if (left != null && right != null) return root;
    return left != null ? left : right;
}

四、二叉搜索树操作

注意:二叉搜索树的中序遍历为升序

4.1 查找节点

java 复制代码
public TreeNode searchBST(TreeNode root, int val) {
    if (root == null || root.val == val) return root;
    return val < root.val ? searchBST(root.left, val) : searchBST(root.right, val);
}

4.2 插入节点

java 复制代码
public TreeNode insertIntoBST(TreeNode root, int val) {
    if (root == null) return new TreeNode(val);
    
    if (val < root.val) {
        root.left = insertIntoBST(root.left, val);
    } else {
        root.right = insertIntoBST(root.right, val);
    }
    
    return root;
}

4.3 删除节点

java 复制代码
public TreeNode deleteNode(TreeNode root, int key) {
    if (root == null) return null;
    
    if (key < root.val) {
        root.left = deleteNode(root.left, key);
    } else if (key > root.val) {
        root.right = deleteNode(root.right, key);
    } else {
        if (root.left == null) return root.right;
        if (root.right == null) return root.left;
        
        TreeNode minNode = findMin(root.right);
        root.val = minNode.val;
        root.right = deleteNode(root.right, root.val);
    }
    return root;
}

private TreeNode findMin(TreeNode node) {
    while (node.left != null) {
        node = node.left;
    }
    return node;
}

五、堆

5.1 大根堆(Max Heap)

java 复制代码
import java.util.Arrays;

public class MaxHeap {
    private int[] heap;
    private int size;
    private int capacity;
    
    public MaxHeap(int capacity) {
        this.capacity = capacity;
        this.size = 0;
        this.heap = new int[capacity];
    }
    
    // 获取父节点索引
    private int parent(int i) {
        return (i - 1) / 2;
    }
    
    // 获取左子节点索引
    private int leftChild(int i) {
        return 2 * i + 1;
    }
    
    // 获取右子节点索引
    private int rightChild(int i) {
        return 2 * i + 2;
    }
    
    // 交换元素
    private void swap(int i, int j) {
        int temp = heap[i];
        heap[i] = heap[j];
        heap[j] = temp;
    }
    
    // 插入元素
    public void insert(int value) {
        if (size >= capacity) {
            System.out.println("Heap is full");
            return;
        }
        
        // 将新元素添加到堆的末尾
        heap[size] = value;
        int current = size;
        size++;
        
        // 向上调整堆
        while (current > 0 && heap[current] > heap[parent(current)]) {
            swap(current, parent(current));
            current = parent(current);
        }
    }
    
    // 删除并返回最大元素
    public int extractMax() {
        if (size <= 0) {
            System.out.println("Heap is empty");
            return Integer.MIN_VALUE;
        }
        
        if (size == 1) {
            size--;
            return heap[0];
        }
        
        // 保存最大值
        int max = heap[0];
        
        // 将最后一个元素移到根节点
        heap[0] = heap[size - 1];
        size--;
        
        // 向下调整堆
        maxHeapify(0);
        
        return max;
    }
    
    // 向下调整堆
    private void maxHeapify(int i) {
        int left = leftChild(i);
        int right = rightChild(i);
        int largest = i;
        
        if (left < size && heap[left] > heap[largest]) {
            largest = left;
        }
        
        if (right < size && heap[right] > heap[largest]) {
            largest = right;
        }
        
        if (largest != i) {
            swap(i, largest);
            maxHeapify(largest);
        }
    }
    
    // 构建最大堆
    public void buildMaxHeap(int[] arr) {
        if (arr.length > capacity) {
            System.out.println("Array size exceeds heap capacity");
            return;
        }
        
        System.arraycopy(arr, 0, heap, 0, arr.length);
        size = arr.length;
        
        // 从最后一个非叶子节点开始调整
        for (int i = (size / 2) - 1; i >= 0; i--) {
            maxHeapify(i);
        }
    }
    
    // 堆排序(升序)
    public void heapSort(int[] arr) {
        buildMaxHeap(arr);
        
        for (int i = size - 1; i > 0; i--) {
            swap(0, i);
            size--;
            maxHeapify(0);
        }
        
        // 恢复原始大小
        size = arr.length;
    }
    
    // 打印堆
    public void printHeap() {
        System.out.print("Heap: ");
        for (int i = 0; i < size; i++) {
            System.out.print(heap[i] + " ");
        }
        System.out.println();
    }
    
    // 测试代码
    public static void main(String[] args) {
        MaxHeap maxHeap = new MaxHeap(10);
        
        // 插入元素
        maxHeap.insert(10);
        maxHeap.insert(5);
        maxHeap.insert(20);
        maxHeap.insert(15);
        maxHeap.insert(30);
        maxHeap.printHeap();
        
        // 提取最大值
        System.out.println("Extracted max: " + maxHeap.extractMax());
        maxHeap.printHeap();
        
        // 堆排序
        int[] arr = {12, 11, 13, 5, 6, 7};
        maxHeap.heapSort(arr);
        System.out.println("Sorted array: " + Arrays.toString(arr));
    }
}

5.2 小根堆(Min Heap)

java 复制代码
import java.util.Arrays;

public class MinHeap {
    private int[] heap;
    private int size;
    private int capacity;
    
    public MinHeap(int capacity) {
        this.capacity = capacity;
        this.size = 0;
        this.heap = new int[capacity];
    }
    
    // 获取父节点索引
    private int parent(int i) {
        return (i - 1) / 2;
    }
    
    // 获取左子节点索引
    private int leftChild(int i) {
        return 2 * i + 1;
    }
    
    // 获取右子节点索引
    private int rightChild(int i) {
        return 2 * i + 2;
    }
    
    // 交换元素
    private void swap(int i, int j) {
        int temp = heap[i];
        heap[i] = heap[j];
        heap[j] = temp;
    }
    
    // 插入元素
    public void insert(int value) {
        if (size >= capacity) {
            System.out.println("Heap is full");
            return;
        }
        
        // 将新元素添加到堆的末尾
        heap[size] = value;
        int current = size;
        size++;
        
        // 向上调整堆
        while (current > 0 && heap[current] < heap[parent(current)]) {
            swap(current, parent(current));
            current = parent(current);
        }
    }
    
    // 删除并返回最小元素
    public int extractMin() {
        if (size <= 0) {
            System.out.println("Heap is empty");
            return Integer.MAX_VALUE;
        }
        
        if (size == 1) {
            size--;
            return heap[0];
        }
        
        // 保存最小值
        int min = heap[0];
        
        // 将最后一个元素移到根节点
        heap[0] = heap[size - 1];
        size--;
        
        // 向下调整堆
        minHeapify(0);
        
        return min;
    }
    
    // 向下调整堆
    private void minHeapify(int i) {
        int left = leftChild(i);
        int right = rightChild(i);
        int smallest = i;
        
        if (left < size && heap[left] < heap[smallest]) {
            smallest = left;
        }
        
        if (right < size && heap[right] < heap[smallest]) {
            smallest = right;
        }
        
        if (smallest != i) {
            swap(i, smallest);
            minHeapify(smallest);
        }
    }
    
    // 构建最小堆
    public void buildMinHeap(int[] arr) {
        if (arr.length > capacity) {
            System.out.println("Array size exceeds heap capacity");
            return;
        }
        
        System.arraycopy(arr, 0, heap, 0, arr.length);
        size = arr.length;
        
        // 从最后一个非叶子节点开始调整
        for (int i = (size / 2) - 1; i >= 0; i--) {
            minHeapify(i);
        }
    }
    
    // 堆排序(降序)
    public void heapSort(int[] arr) {
        buildMinHeap(arr);
        
        for (int i = size - 1; i > 0; i--) {
            swap(0, i);
            size--;
            minHeapify(0);
        }
        
        // 恢复原始大小
        size = arr.length;
    }
    
    // 打印堆
    public void printHeap() {
        System.out.print("Heap: ");
        for (int i = 0; i < size; i++) {
            System.out.print(heap[i] + " ");
        }
        System.out.println();
    }
    
    // 测试代码
    public static void main(String[] args) {
        MinHeap minHeap = new MinHeap(10);
        
        // 插入元素
        minHeap.insert(10);
        minHeap.insert(5);
        minHeap.insert(20);
        minHeap.insert(15);
        minHeap.insert(30);
        minHeap.printHeap();
        
        // 提取最小值
        System.out.println("Extracted min: " + minHeap.extractMin());
        minHeap.printHeap();
        
        // 堆排序
        int[] arr = {12, 11, 13, 5, 6, 7};
        minHeap.heapSort(arr);
        System.out.println("Sorted array: " + Arrays.toString(arr));
    }
}

5.3 Java内置的PriorityQueue可以用作堆

java 复制代码
import java.util.PriorityQueue;
import java.util.Collections;

public class HeapWithPriorityQueue {
    public static void main(String[] args) {
        // 小根堆(默认)
        PriorityQueue<Integer> minHeap = new PriorityQueue<>();
        minHeap.add(10);
        minHeap.add(5);
        minHeap.add(20);
        System.out.println("Min heap: " + minHeap);
        System.out.println("Min element: " + minHeap.peek());
        System.out.println("Extracted min: " + minHeap.poll());
        System.out.println("Min heap after extraction: " + minHeap);
        
        // 大根堆(使用Comparator.reverseOrder())
        PriorityQueue<Integer> maxHeap = new PriorityQueue<>(Collections.reverseOrder());
        maxHeap.add(10);
        maxHeap.add(5);
        maxHeap.add(20);
        System.out.println("\nMax heap: " + maxHeap);
        System.out.println("Max element: " + maxHeap.peek());
        System.out.println("Extracted max: " + maxHeap.poll());
        System.out.println("Max heap after extraction: " + maxHeap);
    }
}
相关推荐
Y200309161 小时前
支持向量机核心知识总结
算法·机器学习·支持向量机
小巫程序Demo日记1 小时前
插入排序讲解
数据结构·算法·排序算法
CoovallyAIHub2 小时前
应对不平衡数据集:MixUp、CutMix与Focal Loss实战指南
深度学习·算法·计算机视觉
NAGNIP3 小时前
一文理解提示微调(Prefix Tuning/Prompt Tuning/P Tuning)
算法
薛定谔的算法3 小时前
深入探索 ES6 中的 Map 数据结构
前端·javascript·算法
CoovallyAIHub3 小时前
AI如何一眼看穿鱼群健康?看改进HRNet模型实现水下健康监测
深度学习·算法·计算机视觉
稳兽龙3 小时前
codeforces(1045)(div2)D. Sliding Tree
c++·算法··路径树
轴测君3 小时前
3 无重复字符的最长子串
数据结构·算法·leetcode
2501_924731114 小时前
智慧城市交通场景误检率↓78%!陌讯多模态融合算法实战解析
人工智能·算法·目标检测·视觉检测·智慧城市