具体创建原理;自行百度,这里仅仅提供实现的思路
import java.util.Arrays;
//usage:
//插入:add
//删除;remove
//查找;contains
//排序:heapSort
// 大根堆建立
// 核心方法:heapInsert和heapify
/**
* 插入元素时候:堆上升
* 删除元素时候:堆下沉
* 堆排序和删除相关
*/
public class BigHeap{
// 大根堆
private int[] heap; // 堆结构
private int size; // 堆中元素数量
private int limit; // 当前堆容量
public BigHeap(int limit){
heap = new int[limit];
this.limit = limit;
this.size = 0;
}
public BigHeap(){
heap = new int[10];
this.limit = 10;
this.size = 0;
}
// 插入
// 真正对外暴露的插入方法 === 可以实现扩容
public void add(int value){
// 空间不够数组扩容 --复制 + 扩容0.75倍
if (this.size + 1 > this.limit){
// copyOf:将数组复制到heap中,并指定新长度,返回新数组
heap = Arrays.copyOf(heap,(int)(this.limit<<1));
this.limit = heap.length;
}
// 插入元素
heap[this.size] = value;
heapInsert(heap,this.size);
this.size++;
}
// 每次插入一个插入元素
// index是当前元素位置 index 范围:0~arr.length-1
private void heapInsert(int[] arr,int index){
while (arr[index] > arr[(index - 1) / 2]){
swap(arr,index,(index - 1)/2);
// 当前元素上移
index = (index - 1) / 2;
}
}
// 删除
// 暴露在外的接口 -- 堆顶 index = 0,非堆顶index != 0
public Integer remove(){
if (this.size == 1){
this.size--;
return heap[this.size];
}
else if (!isEmpty()){
swap(heap,0,this.size-1);
this.size--;
heapify(heap,0);
return heap[this.size];
}
return null;
}
// 删除堆中一个堆顶元素后进行下沉调整 -- 默认删除堆顶元素
private void heapify(int[] arr,int index){
// 要考虑好左右孩子存在的情况,画一下就出来了
// 3种情况
while (index < this.size){
int left = (index<<1 | 1);
int right = ((index<<1) + 2);
// 左右孩子最大元素下标,没有左右孩子返回-1
int maxIndex = right < this.size?(arr[left] <= arr[right]?right:left):(left < this.size?left:-1);
// 判断是否继续下沉 maxIndex == -1说明index没有左右孩子了,调整结束
if (maxIndex == -1 || arr[index] > arr[maxIndex])
break;
swap(arr,index,maxIndex);
// 坐标下沉
index = maxIndex;
}
}
// 删除堆中指定元素 -- 以待删除元素为根的树调整结构
public boolean remove(int value){
// indexOf:求元素下标,-1:没有
if (isEmpty() || indexOf(value) == -1)
return false;
else if (heap[this.size-1] == value){
this.size--;
}
// 最后一个一定不是value,所以可以这末写
for (int i = 0;i < this.size;i++){
if (heap[i] == value){
// 调整结构
swap(heap,i,this.size-1);
this.size--;
heapify(heap,i);
break;
}
}
return true;
}
// 查找
// 查看堆顶元素 -- 只看不删
public int peek(){
return heap[0];
}
//查看堆顶元素 -- 看完删
public int poll(){
return remove();
}
// 查找元素
public boolean contains(int value){
// 非空情况下查找
if (!isEmpty()){
for (int i = 0; i < this.size; i++) {
if (heap[i] == value)
return true;
}
}
return false;
}
// 工具
// 求指定元素的下标
public int indexOf(int value){
if (!isEmpty()){
for (int i = 0; i < this.size; i++) {
if (heap[i] == value)
return i;
}
}
return -1;
}
// 交换两个元素的位置
private void swap(int[] arr,int i,int j){
arr[i] = arr[i] ^ arr[j];
arr[j] = arr[i] ^ arr[j];
arr[i] = arr[i] ^ arr[j];
}
// 判断堆是否为空
public boolean isEmpty(){
return this.size == 0;
}
// 打印数组
public void print(){
if (this.size == 0){
System.out.println("[]");
return;
}
String str = "[";
if (size == 1){
str += heap[0] + "]";
System.out.println(str);
return;
}
for (int i = 0; i < size-1; i++) {
str += heap[i]+",";
}
str += heap[size-1]+"]";
System.out.println(str);
}
// 推排序 --- 每次将最大值删除放到新数组里面 -- 知道原理读者可以自己利用已有方法写
public static void heapSort(int[] arr){
BigHeap b = new BigHeap(1);
if (arr == null || arr.length == 0)
return;
// 插入元素
for (int i = 0; i < arr.length; i++) {
b.add(arr[i]);
}
// 复制回arr中
int length = b.size;
for (int i = 0; i < length; i++) {
arr[i] = b.remove();
}
}
// test
public static void main(String[] args) {
BigHeap b = new BigHeap(1);
int[] arr = new int[]{3,1,2,5,0,89,7};
b.add(1);
System.out.println(b.remove());
b.heapSort(arr);
System.out.println(Arrays.toString(arr));
}
}
大根堆Java实现
于 2022-03-26 11:43:47 首次发布