//堆结构:大根堆------堆排序
//PriorityQueue<Integer> heap = new PriorityQueue<>(); //系统默认的优先级队列(即系统默认堆-小根堆)
//heap.add(5); heap.add(7); //添加5.7元素
//while(!heap.isEmpty){ System.out.print( HEAP.POLL() ); } //打印出所有数
public static class MyMaxHeap{
private int[] heap; //堆-用数组形式表达
private int limit; //
private int heapSize; //记录数组元素的长度
//有参构造器
public MyMaxHeap( int limit) {
heap =new int[limit];
this.limit = limit;
heapSize = 0;
}
//堆排序-大根堆有规律,但没有全局排序,于是我们将第n大值向后与倒数n数交换 :O(N*logN-n个数持续n遍,每遍最多执行2logN次操作,)
public void heapSort(int[] arr) {
if(arr == null || arr.length<2)return; //元素值过少
for(int i=0;i<arr.length;i++) { //将每一个元素视为新添加的元素进行大根堆调整
heapInsert(arr,i);
}
/*当用户不需要全局排序、只需要大根堆时,可以直接用此for代替上一个for。从最末尾位置开始,判定是否需要下沉,直到0索引结束:O(N)
for(int i=arr.length-1;i>=0;i--) {
heapify(arr,i,arr.length);
}
*/
int heapSize = arr.length; //赋值当前数组长度
swap(arr,0,--heapSize); //交换0索引最大值和最末尾值,并且进行元素--操作(即将大值放在数组末尾,同时固定已经放好的大值、不再修改)
while(heapSize > 0) { //一直持续到没有元素
heapify(arr,0,heapSize); //每次将最大值、最末尾位置值交换后,就进行heapify-堆结构整理方法
swap(arr,0,--heapSize);
}
}
//判断数组元素长度是否为0,是否为Limit(即数组的内存长度)
public boolean isEmpty() {
return heapSize == 0;
}
public boolean isFull() {
return heapSize == limit;
}
//判定还有没有内存空间
public void push(int value) {
if(heapSize == limit) { //即数组元素长度达到内存空间长度,输出内存满了
throw new RuntimeException("heap is full");
}
heap[heapSize] = value; //即内存空间还有,就将输入的value作为第heapSize个索引输入
heapInsert(heap,heapSize++); //调用heapInsert方法,对输入的value在大根堆中排序的一部分
}
//
public void pop() {
int max = heap[0]; //找到数组-堆的最大值-索引0
System.out.println(max);
swap(heap,0,--heapSize); //将索引0的数和最后位 heapSize进行交换,同时数组长度-1以删除最大值
heapify(heap,0,heapSize); //将已经是0索引的heapSize-1值(相对最小的值)递归的向子节点比较、交换
}
//index即输入项的节点位置,(index-1)/2即父节点,
public void heapInsert(int[] arr,int index) {
while(arr[index] > arr[(index-1)>>1]) { //如果子节点值>父节点值,就交换位置(判定条件也会排除:index处于最高父节点,这时(index-1)/2等于index)
swap(arr,index,(index-1)>>1);
index = (index-1)>>1; //然后将父节点位置赋值给index
}
}
//将已经是0索引的heapSize-1值(相对最小的值)递归的向子节点比较、交换---即下沉:当没有子节点 或 没有更小值的子节点
public void heapify(int[] arr,int index,int heapSize) { //index:现在的位置
int left = index * 2 +1; //子左节点left,
while(left<heapSize) { //即还未到最小的子节点,或者没有子节点了,即有left左节点且不越界
int largest = left +1 < heapSize && arr[left+1] >arr[left]? left+1: left; //有右子节点,且右子节点>左子节点,就换右子节点,否则换子左节点
//上下代码-将index(父节点)、left(子左节点)、left+1(右子节点)进行判断,谁大赋值给 largest
largest = arr[largest] > arr[index] ? largest : index ; //将子节点大的那个跟父节点index进行判断,子节点大就换
if(largest == index) { //即index父节点更大,直接退出
break;
}
//子节点更大
swap(arr,largest,index); //交换largest 和 index
index = largest; //将largest 赋值给 index
left = index *2 +1; //下一个子节点
}
}
}
//数组元素交换
public static void swap(int[] arr,int i,int j) {
int temp;
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
java:实现堆结构和堆排序
最新推荐文章于 2024-09-05 10:39:00 发布