• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
正在努力成为一个优秀的废物
博客园    首页    新随笔    联系   管理    订阅  订阅
大顶堆和小顶堆

大顶堆:任意非叶子节点的值大于等于其子节点的值。

小顶堆:任意非叶子节点的值小于等于其子节点的值。

堆是完全二叉树,所以可以直接用数组存储。

堆初始化:

堆的初始化使用筛降法,从最后一个非叶子节点开始向下调整直到跟节点。需要建堆的数组长度为n,最后一个元素的下标为n-1,其父节点为 ((n-1) -  1)  >> 1

堆顶元素的删除:

每次只能删除堆顶元素,删除完堆顶元素之后,将最后一个元素放在堆顶,此时的堆不满足堆的性质,需要进行调整。

    /**
     * 向下调整
     *
     * @param i 要调整的编号
     */
    private void siftDown(int i) {
        // 如果父节点比任意一个子节点要大,需要调整,和子节点中较小的那个节点进行互换
        // 只有非叶子节点才需要调整
        int value = nums[i];
        while (2 * i + 1 < len) {
            int left = 2 * i + 1;
            int right = 2 * i + 2;
            // 有右节点,先比较两个左右节点
            int minValueIdx = (right < len && nums[right] < nums[left]) ? right : left;
            // 子节点中比较小的和父节点比较
            if (nums[minValueIdx] < value) {
                // 需要调整
                nums[i] = nums[minValueIdx];
                i = minValueIdx;
            } else {
                // 节点i比孩子节点都小,不用再调整了
                break;
            }
        }
        nums[i] = value;
    }

向堆中添加元素:

每次向堆中添加元素时,直接将元素放在末尾,然后调整新放入元素的位置到正确的位置。

    public void add(int i) {
        if (len < nums.length) {
            nums[len] = i;
            siftUp(len);
            len++;
        }
    }

    /**
     * 向上调整
     *
     * @param i
     */
    private void siftUp(int i) {
        // i = 0时是根节点, 不需要再调整了
        int value = nums[i];
        while (i > 0) {
            int p = (i - 1) >> 1;
            if (nums[p] > value) {
                // 父节点更大, 需要调整
                nums[i] = nums[p];
                i = p;
            } else {
                break;
            }
        }
        nums[i] = value;
    }

 

posted on 2020-03-31 19:44  你算哪根小毛线  阅读(2034)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3