堆排序
堆排序(HeapSort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。
堆排序的步骤:
1、将初始待排序的元素序列(R1,R2….Rn)构建成大顶堆,此堆为初始的无序区;
2、将堆顶元素R[1]与最后一个元素R[n]交换,此时得到新的无序区(R1,R2,……Rn-1)和新的有序区(Rn),且满足R[1,2…n-1]<=R[n];
3、由于交换后新的堆顶R[1]可能违反堆的性质,因此需要对当前无序区(R1,R2,……Rn-1)调整为新堆,然后再次将R[1]与无序
区最后一个元素交换,得到新的无序区(R1,R2….Rn-2)和新的有序区(Rn-1,Rn)。不断重复此过程直到有序区的元素个数为n-1,
则整个排序过程完成。
代码实现:
import java.util.Arrays;
public class HeapSort {
public static void main(String[] args) {
int[] arr = {-1,-2,3,4,7,6,2,1,0,369,258};
System.out.println("未排序前");
System.out.println(Arrays.toString(arr));
heapSort(arr);
System.out.println("排序后");
System.out.println(Arrays.toString(arr));
}
private static void maxHeap(int[] arr,int size,int index) {
/*如果从下标从0开始存储,则编号为i的节点的主要关系为:
双亲:下取整 ((i-1)/2)
左孩子:2i+1
右孩子:2i+2*/
//左子节点和右子节点的下标
int leftNode = 2 * index + 1;
int rightNode = 2 * index +2;
//父节点分别和两个子节点对比大小,找出最大的节点
int max = index;
if (leftNode < size && arr[leftNode] > arr[max]){
max = leftNode;
}
if (rightNode < size && arr[rightNode] > arr[max]){
max = rightNode;
}
//交换位置
if (max != index){
int temp = arr[index];
arr[index] = arr[max];
arr[max] = temp;
//交换位置后可能会影响之前排好的堆,所以再对之前排好的堆重新调整
maxHeap(arr,size,max);
}
}
private static void heapSort(int[] arr) {
//开始的位置-
int start = (arr.length-1-1)/2;
//把数组调整成大顶堆
for (int i = start; i >= 0; i--) {
maxHeap(arr,arr.length,i);
}
//把第一个元素和最后一个元素交换后
//开始调整堆的位置就是从0,因为0索引开始往后的堆已经不符合大顶堆的规则了,
//调整的长度就是i,每次交换完成后向前加一,长度越来越小,直到排序完成。
for (int i = arr.length-1; i >= 0; i--) {
int temp = arr[0];
arr[0] = arr[i];
arr[i] = temp;
maxHeap(arr,i,0);
}
}
}
执行结果: