堆排序
堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序,它的最坏,最好,平均时间复杂度均为O(nlogn),它也是不稳定排序。首先简单了解下堆结构。
'''堆'''是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆
堆排序的基本思想是:将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。如此反复执行,便能得到一个有序序列了
堆排序首先进行建堆
建堆完成后进行排序
大致步骤
a.将无需序列构建成一个堆,根据升序降序需求选择大顶堆或小顶堆;
b.将堆顶元素与末尾元素交换,将最大元素"沉"到数组末端;
c.重新调整结构,使其满足堆定义,然后继续交换堆顶元素与当前末尾元素,反复执行调整+交换步骤,直到整个序列有序。
public static void heapSort( int []arr){
//将数据整理成大顶堆
for (int i=arr.length/2-1;i>=0;i--){
buildHeapSort(arr,i,arr.length);
}
for (int j=arr.length-1;j>0;j--){
//把堆顶元素放到数组最后
swap(arr,0,j);
//堆顶放入数组结尾后 自上而下重新调整数组 建立新的大顶堆
buildHeapSort(arr,0,j);
}
}
/**
* 整个堆排序最关键的地方
*
* @param arr 待组堆
* @param start 起始结点
* @param length 堆的长度
*/
public static void buildHeapSort(int[] arr, int start, int length) {
int temp = arr[start];
//从上到下 将小数下沉到堆底
for (int i = 2 * start + 1; i < length; i = 2 * i + 1) {
//判断左右孩子节点的大小
if (i + 1 < length && arr[i] < arr[i + 1]) {
i++;
}
//父节点与大于父节点的孩子节点进行交换
if (temp < arr[i]) {
swap(arr, start, i);
start = i;
} else {
break; //父节点大于它的左节点和右节点
}
}
}
//用于交换
public static void swap(int[] arr, int x, int y) {
int tem = arr[x];
arr[x] = arr[y];
arr[y] = tem;
}