最大索引堆(IndexMaxHeap)

一、概念及其介绍

索引堆是对堆这种数据结构的优化,是利用真正元素的索引值来组成一个堆,可以映射出一个最大堆或者最小堆,索引堆可分为最大索引堆 (IndexMaxHeap) 和最小索引堆 (IndexMinHeap)

为什么要索引堆:

当我们在使用堆这个数据结构的时候,需要对堆进行一系列的操作,如插入,取出等操作,我们会不断的改变相应数据的位置,此时当数据较大的时候,如每个堆中的数据都是一个较大文本等,在交换位置是就会对计算机有较大消耗;所以这里我们引入索引堆,索引堆是根据比较真正数据,但改变位置的是对应数据索引的位置真正操作的是对应数据的索引,真正数据位置不变,其优点总结如下:

  1. 优化了交换元素的消耗。
  2. 加入的数据位置固定,方便寻找。

二、结构图示实现分析

在这里插入图片描述

实现思想: 比较data数据,交换的是索引元素,首先构造函数添加索引数组属性 indexes

private T[] data;         // 最大索引堆中的数据
private int[] indexes;    // 最大索引堆中的索引
private int count;        // 元素对应的索引
private int capacity;     // 表示堆的容量

相应构造函数调整为,添加初始化索引数组

public IndexMaxHeap(int capacity) {
    data = (T[]) new Comparable[capacity + 1];
    indexes = new int[capacity + 1];
    count = 0;
    this.capacity = capacity;
}

我们要对最大索引堆进行插入操作,这里我们定义一个 insert () 函数

public void insert(int i, T item) {
    assert count + 1 <= capacity;
    assert i + 1 >= 1 && i + 1 <= capacity;

    i += 1;
    data[i] = item;
    // 调整插入操作,indexes 数组中添加的元素是真实 data 数组的索引 indexes [count+1] = i
    indexes[count + 1] = i; 
    count++;
    shiftUp(count);
}

调整 shift up 操作:比较的是 data 数组中父节点数据的大小,所以需要表示为 data[index[k/2]] < data[indexs[k]],交换 index 数组的索引,对 data 数组不产生任何变动,shift down 同理。

private void shiftUp(int k) {
    while (k > 1 && data[indexes[k / 2]].compareTo(data[indexes[k]]) < 0) {
        swapIndexes(k, k / 2); // 交换索引
        k /= 2;
    }
}

我们要对最大索引堆中元素进行取出,其逻辑和堆一样,我们也需要将 data [1] 改为 data [indexes [1]];( 与 shiftUp () 同理 )

public T extractMax() {
    assert count > 0;
    T ret = data[indexes[1]];
    swapIndexes(1, count);
    count--;
  
    shiftDown(1);
    return ret;
}

下面来实现 shiftDown (),其数组索引方法和 shiftUp () 同理

private void shiftDown(int k) {
    while (2 * k <= count) {
        int j = 2 * k;
        if (j + 1 <= count && data[indexes[j + 1]].compareTo(data[indexes[j]]) > 0)
            j++;
        if (data[indexes[k]].compareTo(data[indexes[j]]) >= 0)
            break;
        swapIndexes(k, j);
        k = j;
    }
}

在索引堆中还有一个重要的功能,就是我们需要更新索引堆里的元素,传入需要改变值对应的索引 i,和修改元素值 newItem

public void change(int i, T newItem) {
    i += 1;
    data[i] = newItem;
    // 找到indexes[j] = i, j表示data[i]在堆中的位置
    // 之后shiftUp(j), 再shiftDown(j)
    for (int j = 1; j <= count; j++)
        if (indexes[j] == i) {
            shiftUp(j);
            shiftDown(j);
            return;
        }
}

三、完整代码示例

https://github.com/perkinls/java-summary/

关注公众号 ,专注于java大数据领域离线、实时技术干货定期分享!如有问题随时沟通交流! www.lllpan.top

在这里插入图片描述

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值