索引堆

与普通堆相比,节点存储的是数据的索引,维护时比较数据,但交换索引。
适用于数据非常复杂,交换起来比较耗时,或者我们堆中的数据和索引有固定关系的情况,在构建为堆之后会破坏这些关系,在希望修改数据时会比较麻烦,因此可以使用索引堆。
为了完成修改操作,但不需要遍历索引数组的需求,引入反向索引。
reverse[i]表示索引i在index数组中的位置(经典思想)
index[i] = j;
reverse[j] = i;

index[reverse[i]] = i;
reverse[index[i]] = i;

public class IndexMaxHeap {
	private int capacity;
	private int count = 0;
	private int[] data;
	private int[] index;
	private int[] reverse;
	public IndexMaxHeap(int capacity){
		this.capacity = capacity;
		data = new int[capacity+1];
		index = new int[capacity+1];
		reverse = new int[capacity+1];
	}
	public IndexMaxHeap(int[] arr){
		int n = arr.length;
		data = new int[n+1];
		this.capacity = n;
		for(int i = 0;i<n;i++)
			data[i+1] = arr[i];
		count = n;
		for(int i = count/2;i>0;i--)
			shiftDown(i);
	}
	public int size(){
		return count;
	}
	public boolean isEmpty(){
		return count==0;
	}
	public void insert(int i,int item){
		try {
			i+=1;
			data[i] = item;
			index[count+1] = i;
			reverse[i] = count+1;
			count++;
			shiftUp(count);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	public int popIndex(){
		int ans = index[1]-1;
		swap(index,1,count);
		reverse[index[1]] = 1;
		reverse[index[count]] = 0;
		count--;
		shiftDown(1);
		return ans;
	}
	public int getItem(int i){
		return data[i+1];
	}
	private void shiftUp(int k){
		while(k>1&&data[index[k/2]]<data[index[k]]){
			swap(index,k/2,k);
			reverse[index[k/2]] = k/2;
			reverse[index[k]] = k;
			k/=2;
		}
	}
	private void shiftDown(int k){
		int val = data[index[k]];//用赋值的方法保存下来要调整的数据
		while(2*k<=count){
			int j = 2*k;//左右孩子中比较大的
			if(j+1<=count&&data[index[j+1]]>data[index[j]])
				j+=1;
			/*if(data[index[k]]>data[j])
				break;
			swap(index,j,k);//用交换的方法,时间复杂度比较高
			reverse[index[j]] = j;
			reverse[index[k]] = k;
			k = j;*/
			
			//用赋值的方法
			if(val>data[index[j]]){
				data[index[k]] = val;
				break;
			}
			data[index[k]] = data[index[j]];
			k = j;
		}
		if(val<data[index[k]])
			data[index[k]] = val;
	}
	
	public void change(int i,int newItem){
		i+=1;
		data[i] = newItem;
		int j = reverse[i];
		shiftUp(j);
		shiftDown(j);
	}
	private void swap(int[] data,int i,int j){
		int temp = data[i];
		data[i] = data[j];
		data[j] = temp;
	}
}

所以在交换索引之后,要更新reverse数组的值。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值