堆的基本概念
堆就是由完全二叉树构成的,而完全二叉树又包括满二叉树或者从左往右依次填充叶结点的树,即要么没有叶节点,如果只有一个叶节点必然是左叶结点。
堆结点的关系
父节点下标为i,则左孩子的坐标为2i+1,右孩子的坐标为2i+2.注下标从0开始
堆排序的步骤
第一步:
根据给出的数据建立堆,本题是升序排列,所以建立大根堆(如果降序排列则建立小根堆,至于为何,看完剩下的步骤就知道了)
public static void heapInsert(int[]arr,int index){
while (arr[(index-1)/2]<arr[index]){
//每个元素寻找自己的父节点,然后与父节点的值进行比较
swap(arr,index,(index-1)/2);
//交换后其余大小关系又会发生改变,所以要继续向上比较,判断是否要继续交换
index=(index-1)/2;
}
}
第二步:
1:将所有数据进行大根堆创建完成后(元素大小为size),根节点就是所有元素中的最大值,此时将根节点与最后一个元素进行交换位置,size–,此时最末尾元素就是我们需要的最大的元素。(每次得到一个值,所以我们要对堆进行size次处理)
2:由于最大的元素与最末尾元素交换了位置,此时大根堆的结构遭到破坏,我们就需要对大根堆进行调整,使它满足大根堆的结构
如何对结构被破坏的大根堆进行调整?
public static void heapify(int[]arr,int index,int size){
int left=2*index+1;
while (left<size) {
int larget = (left + 1 < size && arr[left] < arr[left + 1]) ? left + 1 : left;
larget=arr[larget]>arr[index]?larget:index;
if (larget==index)
break;
swap(arr,larget,index);
index=larget;
left=index*2+1;
}
}
1:index是交换完位置之后根节点的位置,我们首先要与size比较,判断该结点是否有左右孩子,然后找到左右结点中的最大值,如果交换后的根节点就是最大值,即larget==size,则break,否则交换index和larget的位置,然后继续进行往下判断。
整体代码:
package chap1;
import java.util.Arrays;
/**
* @author your_tt
* @date 2021年05月28日16:11
*/
public class OwnHeapSort {
public static void HeapSort(int[] arr){
if (arr.length<2 ||arr==null){
return;
}
for (int index=0;index<arr.length;index++){
heapInsert(arr,index);
}
int size=arr.length;
swap(arr,0,--size);
while (size>0){
heapify(arr,0,size);
swap(arr,0,--size);
}
}
public static void heapInsert(int[]arr,int index){
while (arr[(index-1)/2]<arr[index]){
swap(arr,index,(index-1)/2);
index=(index-1)/2;
}
}
public static void heapify(int[]arr,int index,int size){
int left=2*index+1;
while (left<size) {
int larget = (left + 1 < size && arr[left] < arr[left + 1]) ? left + 1 : left;
larget=arr[larget]>arr[index]?larget:index;
if (larget==index)
break;
swap(arr,larget,index);
index=larget;
left=index*2+1;
}
}
//交换
public static void swap(int arr[],int i,int j){
int t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
public static void main(String[] args) {
int[] test={9,8,7,6,5,4,3,2,1,88};
HeapSort(test);
System.out.println(Arrays.toString(test));
}
}