递归和非递归的转化--
大部分情况下,递归实现和非递归实现在思路上没有太大的差别,递归实现首先考虑递归结束条件;循环考虑循环变量和单次循环内需要做的事;
package org.example;
import java.util.Arrays;
public class HeapSort {
public static void main(String[] args) {
int[] arr={12,11,10,9,8,7,6,5,4,3,2,1};
heapSort(arr);
System.out.println(Arrays.toString(arr));
}
public static void heapSort(int[] arr){
for (int i = arr.length/2-1; i >=0; i--) {
adjustHeap1( arr,i,arr.length);
}
int temp=0;
/*
将其与末尾元素进行交换,此时末尾就为最大值。
然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。如此反复执行,便能得到一个有序序列了。*/
for (int j=arr.length-1;j>0;j--){
temp=arr[j];
arr[j]=arr[0];
arr[0]=temp;
adjustHeap1(arr,0,j);
}
}
//非递归实现
//思路:
//分别和左右子节点比较,如果左右子节点中有更大的,则交换,然后继续调整被交换的子节点;
//如果没有发生交换或者没有子节点,则说明堆结构调整完成;
/*入参:数组,学要调整的堆顶下标,堆长度(堆中最后一个子节点的下标)*/
static void adjustHeap(int[]arr,int heaphead,int heaplength){
while(heaphead<heaplength){
int left=heaphead*2+1;
int right=heaphead*2+2;
//右子节点存在时(左子节点也存在)
if(right<heaplength){
if(arr[heaphead]<arr[left]&&arr[left]<arr[right]||arr[heaphead]>arr[left]&&arr[left]<arr[right]){
int temp=arr[heaphead];
arr[heaphead]=arr[right];
arr[right]=temp;
heaphead=right;
}else if(arr[heaphead]<arr[left]&&arr[left]>arr[right]){
int temp=arr[heaphead];
arr[heaphead]=arr[left];
arr[left]=temp;
heaphead=left;
}else{
break;
}
//只存在左子节点
}else if(left<heaplength){
if(arr[heaphead]<arr[left]){
int temp=arr[heaphead];
arr[heaphead]=arr[left];
arr[left]=temp;
}
break;
//本身就是叶子节点
}else{
break;
}
}
}
public static void adjustHeap2(int[] arr,int i,int length){
//第一步把数组 {4,6,8,5,9}调整排序为{4,9,8,5,6}
//k=i*2+1 是循环对应的左子树元素
//记录当前要调整的元素
int temp=arr[i];
for (int k=i*2+1;k<length;k=k*2+1){
//把当前左子树和右子树的数据作比较,更换较大的数据
if (k+1<length&&arr[k]<arr[k+1]){
k++;
}
if (arr[k]>temp){
//交换位置
arr[i]=arr[k];
i=k;
}else{
break;
}
}
arr[i]=temp;
}
//递归实现
static void adjustHeap1(int[]arr,int heaphead,int heaplength){
if(heaphead>=heaplength)
return;
int left=heaphead*2+1;
int right=heaphead*2+2;
if(left>=heaplength)
return;
//右子节点存在时(左子节点也存在)
if(right<heaplength){
if(arr[heaphead]<arr[left]&&arr[left]<arr[right]||arr[heaphead]>arr[left]&&arr[left]<arr[right]){
int temp=arr[heaphead];
arr[heaphead]=arr[right];
arr[right]=temp;
adjustHeap1(arr,right,heaplength);
}else if(arr[heaphead]<arr[left]&&arr[left]>arr[right]){
int temp=arr[heaphead];
arr[heaphead]=arr[left];
arr[left]=temp;
adjustHeap1(arr,left,heaplength);
}else{
return;
}
//只存在左子节点
}else if(left<heaplength){
if(arr[heaphead]<arr[left]){
int temp=arr[heaphead];
arr[heaphead]=arr[left];
arr[left]=temp;
}
return;
//本身就是叶子节点
}
}
}