You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java节点式最大堆实现求助:插入100条字符串效率极低

为啥你的链式最大堆插入这么慢?

嘿,我一眼就瞅出问题所在了:你用findSpot(root)遍历整个堆来找有空位的父节点,这种方式每次插入都要从头扫一遍树,时间复杂度是O(n),插100个元素就得做100次遍历,总复杂度直接飙到O(n²),可不就慢嘛!

怎么优化?用队列跟踪可用父节点啊!

链式堆没法像数组堆那样直接用索引算父/子位置,但我们可以用队列来记录那些还没填满子节点的父节点,这样每次找父节点都是O(1)的操作,插入效率直接拉满:

  • 初始化的时候搞个队列,插入根节点后就把根节点丢进队列。
  • 每次插新节点时,取队列的队首节点:
    • 如果它没左子节点,就把新节点挂左子节点,然后把新节点加入队列(以后它也能当父节点),同时把当前队首节点留在队列里(它还有右子节点的空位)。
    • 如果它没右子节点,就把新节点挂右子节点,这时候这个父节点的两个坑都填满了,直接把它从队列里移除,再把新节点加进队列就行。
  • 对了!别忘了最大堆的上浮调整,你之前的代码好像没做这个——光插节点不调整,那只是棵完全二叉树,根本不是最大堆!
给你补全优化后的代码(Java)
import java.util.LinkedList;
import java.util.Queue;

public class MaxHeap {
    private MyNode root;
    private Queue<MyNode> availableParents;

    public MaxHeap() {
        availableParents = new LinkedList<>();
    }

    public void insert(String name) {
        MyNode node = new MyNode(name);
        if (root == null) {
            root = node;
            availableParents.add(root);
        } else {
            MyNode parent = availableParents.peek(); // 取队首但不移除
            if (parent.lChild == null) {
                parent.lChild = node;
                node.setParent(parent);
                availableParents.add(node); // 新节点未来可作为父节点
            } else {
                parent.rChild = node;
                node.setParent(parent);
                availableParents.add(node);
                availableParents.poll(); // 该父节点已无空位,移出队列
            }
            // 关键:最大堆上浮调整,保证父节点值大于子节点
            heapifyUp(node);
        }
    }

    // 上浮调整逻辑
    private void heapifyUp(MyNode node) {
        while (node.getParent() != null && node.getData().compareTo(node.getParent().getData()) > 0) {
            // 交换当前节点和父节点的数据
            String temp = node.getData();
            node.setData(node.getParent().getData());
            node.getParent().setData(temp);
            // 继续往上调整
            node = node.getParent();
        }
    }

    // 你的MyNode类实现示例
    private static class MyNode {
        private String data;
        private MyNode parent;
        private MyNode lChild;
        private MyNode rChild;

        public MyNode(String data) {
            this.data = data;
        }

        // 必要的getter和setter
        public String getData() { return data; }
        public void setData(String data) { this.data = data; }
        public MyNode getParent() { return parent; }
        public void setParent(MyNode parent) { this.parent = parent; }
        // 左右子节点的getter/setter自己补全就行
    }
}
额外碎碎念

如果不是业务强制要求用链式结构,其实数组实现的最大堆效率更高——直接用索引计算父节点((i-1)/2)和子节点(2i+1、2i+2),不需要维护节点间的引用,插入和调整都更快。但如果必须用链式,队列跟踪可用父节点就是最优解啦!

内容的提问来源于stack exchange,提问作者James

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 06:48:58