MaxHeap
用二叉树实现堆:
用数组存储二叉堆:
基于数组实现二叉堆:
package com.lt.datastructure.MaxHeap; public class MaxHeap<E extends Comparable<E>> { private Array1<E> data; public MaxHeap(int capacity) { data = new Array1<>(capacity); } public MaxHeap() { data = new Array1<>(); } public int size() { return data.getSize(); } public boolean isEmpty() { return data.isEmpty(); } //返回一个索引的父亲结点的索引 private int parent(int index){ if(index==0){ throw new IllegalArgumentException("index 0 doesn't have parent."); } return (index-1)/2; } //返回完全二叉树数组表示中,一个索引所表示的元素的左孩子结点的索引 private int leftChild(int index){ return index*2+1; } //返回完全二叉树数组表示中,一个索引所表示的元素的右孩子结点的索引 private int rightChild(int index){ return index*2+2; } //向堆中添加元素siftUp public void add(E e){ //添加元素 data.addLast(e); //给添加的新元素e设置索引为data.getSize()-1; siftUp(data.getSize()-1); } private void siftUp(int k) { while(k>0 && data.get(parent(k)).compareTo(data.get(k))<0){ //如果父亲结点的值比孩子结点的值小,交换索引处的值 data.swap(k,parent(k)); //继续while循环判断新的父亲结点是否符合规则 k = parent(k); } } //看堆中的最大元素,索引大的为父亲结点,所以0处的值最大 public E findMax(){ if(data.getSize()==0){ throw new IllegalArgumentException("Can not finMax when heap is null"); } return data.get(0);//索引为0的元素 } //删除堆中最大元素并返回 public E extractMax(){ E ret = findMax(); data.swap(0,data.getSize()-1);//交换索引处的值 data.removeLast();//删除了堆中最大元素 siftDown(0);//下沉 return ret;//将被删除的最大值返回 } //完成下沉操作 //找到左右孩子中较大值j,如果k所在的值大于j所在的值,那么结束循环,否则继续下潜 private void siftDown(int k) { //当k为叶子结点,循环结束,即左孩子索引越界(右孩子结点比左孩子大) while(leftChild(k)<data.getSize()){ int j = leftChild(k); //如果有右孩子,且右孩子大于左孩子的值,那么j为右孩子 if(j + 1<data.getSize() && data.get(j+1).compareTo(data.get(j))>0){ j ++; } //如果k没右孩子,或者有右孩子但值左孩子值比左孩子小,此时data[j]是左右孩子中较大值 //此时如果k大于等于左右孩子的最大值,那么没有违反堆的性质,下沉操作结束 if(data.get(k).compareTo(data.get(j))>=0){ break; } //否则违反了堆的性质,继续交换 data.swap(k, j); k = j; } } /* replace:取出最大元素且替换成新的元素e,返回被替换的最大元素 * 实现方法: 1 先extract,再add 复杂度 :两次logn × * 2 直接替换,然后siftDown 复杂度:一次 logn ✔ */ public E replace(E e){ E ret = findMax(); //将堆顶换成新元素e,但可能违背堆的性质,所以需要进行下潜操作 data.set(0, e); siftDown(0); return ret; } /* heapify(堆化,转化为堆):将任意数组整理成堆的形状 * 只要合理的交换数组中的位置,其实也可以完成这样的操作,但是有更快的操作 * 1 扫描数组,放入堆 × (将n个元素逐个放入空堆中,复杂度O(nlogn)) * 2 抛弃叶子节点。从(倒数第一个非叶子节点的索引:最后一个节点的父亲结点)依次向前遍历,进行siftDown,从而变成一个最大堆 ✔ * heapify的过程: 算法复杂度为O(n) */ public MaxHeap(E[] arr){ //此处在动态数组新建了构造 data = new Array1<>(arr); //从最后一个结点的父亲结点开始向前遍历,对每个元素做下沉操作 for(int i = parent(arr.length-1) ; i>=0 ; i--){ siftDown(i); } } @Override public String toString() { return "MaxHeap [data=" + data + "]"; } }
堆测试:
数组的堆化测试:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端