* 堆排序和简单选择排序都是选择排序
* 堆排序:将数组看成完全二叉树的结构,根据数组的顺序下标建立抽象的二叉树(需要理解);有大根堆和小根堆;
* 插入实现的思想:每次插入的都是叶子节点,插入的时候根据数组的下标作为依据进行判断:插入元素的父节点(i-1)/2的值是否大于等于插入的节点,如果是不做处理,
* 否则,将两者数据进行互换,同时索引指针指向父节点,在进行验证,while循环条件为 arr[(index-1)/2]<arr[index]
* 弹出实现思想:首先将第一个元素与数组的最后一个元素互换位置,这样就打破了堆排序的结果,然后对从上到下进行重新验证同时限制数组的长度n-1(每次弹出一个,-1),
* 如果插入元素小于子节点(首先得出最大的子节点),互换位置,然后修改指针,在进行下面子节点的验证,while循环条件left不能越界
* 时间复杂度O(n*logn)
* 空间复杂度 O(1)
* 稳定性:不稳定算法
public class HeapSorting {
public static void heapSort(int[] arr){
if(arr==null||arr.length<2){
return;
}
heapSort(arr,0,arr.length-1);
}
/**
*
* @param arr
* @param l 数组起点
* @param j 数组长度
*/
private static void heapSort(int[] arr, int l, int j) {
for(int i=0;i<arr.length;i++){
// 逐步形成大根堆
heapInsert(arr,i);
}
// 交换拍好的大根堆和最后的一个值
swap(arr,0,j--);
// 交换之后,不再是大根堆形式,进行下一步排序
while(j>0){
heapSortdown(arr,0,j);
// System.out.println("谁动了我的奶酪"+j);
// System.out.println(arr[j]);
swap(arr,0,j--);
System.out.println("谁动了我的奶酪"+j);
}
}
/**
* 弹出大根堆,重新向下排序,
* @param arr 待排序数组+末尾排好序的数
* @param size 待排序数组的长度
*/
private static void heapSortdown(int[] arr,int index, int size) {
// 小心越界
int left = index*2+1;
while(left<size){
// 先判断两个子孩子谁大,获取最大的节点;注意下面代码中<=中的等号必须有,可以考虑一下数组为{1,3,2}时候的场景
int largest = left+1<=size && arr[left]>arr[left+1]?left:left+1;
// 如果新放入的值大于子节点的最大值,说明有序。返回
largest = arr[largest] > arr[index] ? largest : index;
if (largest == index) {
// return和break效果都是一样的
return;
}
// 否则交换父节点和最大的子节点
swap(arr,index,largest);
// 将索引值下标改为最大下标
index=largest;
// 修改子节点的下标
left=index*2+1;
}
// 错误做法;
/* int left=(index-1)/2;;
int largest = arr[left]>arr[left+1]?left:left+1;
while(arr[index]<arr[largest]){
swap(arr,arr[index],arr[largest]);
index=left;
left=(index-1)/2;
}*/
}
private static void heapInsert(int[] arr, int index) {
// 正确插入验证:循环条件:父节点的值是否大于子值
while(arr[(index-1)/2]<arr[index]){
// 如果大于交换
swap(arr,(index-1)/2,index);
// 修改索引下标,进行向上验证
index=(index-1)/2;
}
// 错误之处,如果i=8,arr[i]=4;(i-1)/2=3,arr[3]=5;这个循环就成了死循环。
/* while(index>0){
int fuValue = (index-1)/2;
if(arr[fuValue]<arr[index]){
System.out.println(arr[fuValue]+" "+arr[index]);
swap(arr,fuValue,index);
index=fuValue;
}
}*/
}
// 交换两个数的值
public static void swap(int[] arr,int i,int minValue){
int temp =arr[i];
arr[i] =arr[minValue];
arr[minValue]=temp;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] arr = {1,3,5,7,9,2,4,6,8};
heapSort(arr);
for (int i : arr) {
System.out.println(i);
}
}
}