手写加强堆

您所在的位置:网站首页 java手写文字识别 手写加强堆

手写加强堆

2023-06-07 09:32| 来源: 网络整理| 查看: 265

为什么要手写加强堆?

因为系统提供的堆(PriorityQueue)没有反向索引表,无法快速找到元素和删除某个元素,如果要实现的话查找的代价是O(N),删除元素的代价是O(N*logN)

直接上代码,看不懂的私信我

package dataStructure.heap; import java.util.Comparator; import java.util.HashMap; /** * 自写加强堆 * 可以实现低成本删除任意元素 * @param */ public class HeapGreater { //反向索引表,用于记录某个元素在heap数组中的下标,主要用于快速删除元素 HashMap reverseIndex = new HashMap(); T[] heap; int limit; int heapSize; //T类型的比较器 Comparator comp; public HeapGreater(int limit, Comparator comp) { heap = (T[])new Object[limit]; this.limit = limit; heapSize = 0; this.comp = comp; } //堆是否为空 public boolean isEmpty() { return heapSize == 0; } //堆是否已满 public boolean isFull() { return heapSize == limit; } //删除一个元素并重新调整为大根堆 public void remove(T t) { //为空不可能删除 if(isEmpty()) { throw new RuntimeException("heap is empty"); } //没有这个元素无法删除 if(!reverseIndex.containsKey(t)) { return; } //反向索引表获取元素在数组中的下标 int index = reverseIndex.get(t); //交换要删除的元素和堆中最后一个元素 //heapSize-- swap(heap, index, --heapSize); //元素要删除,反向索引表也应该删除 reverseIndex.remove(t); //删除以后重新调整,最后一个元素已经换到了index位置,从index位置向下调整 heapify(index); //从index往上调整,向上和向下只会发生一个 heapInsert(index); } //弹出堆顶元素并重新调整成大根堆 public T pop() { if(isEmpty()) { throw new RuntimeException("heap is empty"); } //取到堆顶元素 T t = heap[0]; //把堆顶和堆中最后一个元素交换 swap(heap, 0, --heapSize); //反向索引表删除要删除的元素 reverseIndex.remove(t); //重新调整为大根堆 heapify(0); return t; } /** * 从index开始向下调整大根堆 * @param index */ public void heapify(int index) { //取到当前节点的左孩子 int left = index * 2 + 1; //左孩子是两个孩子里下标比较小的,如果它都不在堆里,就无需调整 while(left < heapSize) { //找到两个孩子里比较大的那个 int largest = left + 1 >= heapSize? left : comp.compare(heap[left], heap[left + 1]) >= 0? left : left + 1; //largest取当前值和最大孩子里最大那个 largest = comp.compare(heap[largest],heap[index]) < 0? index : largest; //如果最大值是自己直接返回 if(largest == index) return; //如果不是则交换自己和最大孩子 swap(heap, largest, index); //当前节点已调整到最大孩子位置,继续调整 index = largest; left = 2 * index + 1; } } //往堆里添加一个元素 public void push(T t) { if(isFull()) { throw new RuntimeException("heap is full"); } heap[heapSize] = t; //添加反向索引表记录 reverseIndex.put(t, heapSize); heapInsert(heapSize ++); } //从index向上调整大根堆 public void heapInsert(int index) { while(comp.compare(heap[index], heap[(index -1 )/2]) > 0) { swap(heap, index, (index - 1)/2); index = (index - 1) / 2; } } //交换i和j位置的元素 private void swap(T[] heap, int i, int j) { //自己跟自己不需要调整 if(i == j) return; T temp = heap[i]; //反向索引表i位置元素防止在j位置 reverseIndex.put(temp,j); heap[i] = heap[j]; //i位置放置原来j位置的元素(已经交换到heap[j]) reverseIndex.put(heap[i], i); heap[j] = temp; } public static void main(String[] args) { HeapGreater heapGreater = new HeapGreater(5, (a,b) -> a - b); heapGreater.push(2); heapGreater.push(3); heapGreater.push(5); heapGreater.push(1); heapGreater.push(4); heapGreater.remove(4); System.out.println(heapGreater.reverseIndex.size()); } }



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3