大根堆和堆排序

本文介绍了大根堆的概念,包括其特点(最大值在根节点),以及关键操作如插入和调整堆的过程。通过实例代码展示了如何使用`heapInsert`和`heapify`方法来维护堆的特性。适合学习和实践堆数据结构的朋友。
摘要由CSDN通过智能技术生成

堆(Heap)是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵完全二叉树的数组对象。

大根堆和小根堆介绍:

  • 大根堆:任意一颗子树,其最大值在树根处的堆结构
  • 小根堆:任意一颗子树,其最小值在树根处的堆结构

堆结构根节点和叶子节点坐标索引关系

  • 任意i位置的节点其左子节点的坐标索引为:2*i+1
  • 任意i位置的节点其右子节点的坐标索引为:2*i+2
  • 任意i位置的节点其父节点的索引坐标为 :(i-1)/2 (向下取整)

对于一个堆结构,需要实现两个基本的方法用来维护堆的特点,一个向上调整,即将其调整到所有小于它的父节点上面去(上浮);一个向下调整,将所有大于它的子节点向上调(下沉),具体见代码实现:

import cn.algorithms.util.ArrayUtil;

/**
 * Created with IntelliJ IDEA.
 *
 * @Description:
 * @Auther: TaoistQu
 * @Date: 2021/05/16/17:25
 */
public class HeapUtil {
    /**
     * @param arr
     * @param index 给定的要插入的索引位置
     */
    public static void heapInsert(int[] arr, int index) {
        while (arr[index] > arr[((index - 1) / 2)]) {
            ArrayUtil.swap(arr, index, (index - 1) / 2);
            index = (index - 1) / 2;
        }
    }

    /**
     * @param arr      堆数组
     * @param index    要开始modify的位置
     * @param heapSize 堆的大小
     */
    public static void heapify(int[] arr, int index, int heapSize) {
        int left = index * 2 + 1;
        while (left < heapSize) {
            int largest = (left + 1) < heapSize && arr[left + 1] > arr[left] ? (left + 1) : left;
            largest = arr[largest] > arr[index] ? largest : index;
            if (largest == index) {
                break;
            }
            ArrayUtil.swap(arr, largest, index);
            index = largest;
            left = index * 2 + 1;
        }
    }
}

利用这两个核心方法实现一个自己的堆:

package cn.dataStructures.heap;

import cn.algorithms.util.ArrayUtil;
import cn.dataStructures.heap.util.HeapUtil;

/**
 * Created with IntelliJ IDEA.
 *
 * @Description: 大根堆 即为完全二叉树 任意一颗子树的最大值在树根上
 * <p>
 * i位置的节点的
 * 左子节点索引为:2*i+1
 * 右子节点索引坐标为:2*i+2
 * 父节点坐标为: (i-1)/2
 * </p>
 * @Auther: TaoistQu
 * @Date: 2021/05/15/19:18
 */
public class Heap {


    private int[] heap;
    private final int limit;
    private int heapSize;

    public Heap(int limit) {
        heap = new int[limit];
        this.limit = limit;
        heapSize = 0;
    }

    public boolean isEmpty() {
        return heapSize == 0;
    }

    public boolean isFull() {
        return heapSize == limit;
    }

    public void push(int value) {
        if (heapSize == limit) {
            throw new RuntimeException("heap is full");
        }
        heap[heapSize] = value;
        HeapUtil.heapInsert(heap, heapSize++);
    }

    public int pop() {
        int ans = heap[0];
        ArrayUtil.swap(heap, 0, --heapSize);
        HeapUtil.heapify(heap, 0, heapSize);
        return ans;
    }
}

详细代码github地址

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值