堆的基本操作

堆:逻辑上是一颗完全二叉树

物理上是数组的形式 ,顺序存储

作用:找数组中的前K大的值

特点:

​ 大顶堆:任意一个root的值>=左右子树的值

​ 小顶堆:任意一个root的值<=左右子树的值

–要调整root所在的节点

前提:root的左右子树都已满足堆的性质

如果root所在的节点已经是叶子结点,调整结束

找到左右孩子中较小的一个min

堆的基本操作(以大顶堆为例)

查找堆元素的父节点,左右子树节点:

``

//数组下标为0的元素也存储数据的情况
//返回完全二叉树的数组表示中,
// 一个索引表示的元素的父亲节点的索引
private int parent(int index) {
    if(index == 0)
        throw new IllegalArgumentException("0没有父亲节点");
    return (index-1)/2;
}
//返回完全二叉树的数组表示中,
// 一个索引表示的元素的左孩子节点的索引
private int leftChild(int index) {
    return index*2 + 1;
}
//返回完全二叉树的数组表示中,
// 一个索引表示的元素的右孩子节点的索引
private int rightChild(int index) {
    return index*2 + 2;
}

添加元素:

``

//向堆中添加元素
public void add(E e) {
    data.add(e);
    siftUp(data.size()-1);
}

private void siftUp(int k) {

    while(k > 0 &&
            //data的父亲节点如果小于data,就交换data与父亲节点
            data.get(parent(k)).compareTo(data.get(k)) < 0) {
        swap(k,parent(k));
        k = parent(k);
    }

}

//交换元素:使用Collections工具类的swap方法

``

private void swap(int i,int j) {
    if(i < 0 || i >= data.size() || j < 0 || j > data.size())
        throw new IllegalArgumentException("非法下标");
    Collections.swap(data,i,j);
}

取出堆中最大元素:

``

//查看堆中最大元素(堆顶)
public E peek() {
    if(data.size() == 0)
        throw new IllegalArgumentException("当前为空堆");
    return data.get(0);
}

//取出堆中最大元素(删除)
public E extractMax() {
    E ret = peek();
    swap(0,data.size() -1);
    data.remove(data.size()-1);
    siftDown(0);
    return ret;
}
private void siftDown(int k) {

    while(leftChild(k) < data.size()) {
        //比较k节点的左右节点中较大的一个
        int j = leftChild(k);
        if(j+1 < data.size() && data.get(j+1).compareTo(data.get(j)) > 0) {
            j = rightChild(k);
            //data[j]时左右子节点中较大值

        }
        if(data.get(k).compareTo(data.get(j)) >= 0) {
            break;
        }
        swap(k,j);
        k = j;
    }
}

replace方法,替换堆顶元素

``

//取出堆中最大元素,并替换为元素e
public E replace(E e) {
    E ret = peek();
    data.set(0,e);
    siftDown(0);
    return ret;
}

heapify方法,将传入的数组改造为堆

``

//将任意数组整理成堆的形状
public void heapify(Integer[] arr){
    if(arr == null)
        throw new IllegalArgumentException("非法数组");
    for(int i = parent(arr.length - 1) ;i >= 0;i--) {
        siftDown(i);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值