既然开了算法和数据结构目录,那这些以前都看烂的一些排序算法还是补充一下吧,毕竟这些排序算法还是挺重要的。
堆排序
1. 堆排序是利用堆这种数据结构而设计的一种排序算法。
2. 堆排序是一种选择排序。
3. 它的最坏,最好,平均时间复杂度均为O(nlogn),也是不稳定排序。
堆
1. 堆是一棵顺序存储的完全二叉树。
2. 大顶堆和小顶堆
小顶堆: 每个结点的关键字都不大于其孩子结点的关键字(arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2])
大顶堆: 每个结点的关键字都不小于其孩子结点的关键字(arr[i] >= arr[2i+1] && arr[i] >= arr[2i+2])
3.如下图
堆排序核心思想和具体步骤
核心思想:
1. 将待排序序列构造成一个大顶堆(从最后一个非叶子结点开始,每次都是从父结点、左孩子、右孩子中进行比较交换,找出最大值或者最小值。从数组结构可以算出 最后一个非叶子节点位置 = [array.length / 2 - 1])。
2. 将堆顶元素(大顶堆根节点最大)和末尾元素交换,此时末尾就是最大值。
3. 将剩余N-1个元素重新构造(由于步骤2的交换导致剩余的元素不满足堆的结构了)。
4. 执行步骤2。
5. 升序构造大顶堆,降序构造小顶堆。
最大堆构建具体步骤:
堆排序具体步骤:
代码实现
public class HeapSort {
/**
* @Description 排序
* @Author wayne
* @Param
* @Date 2019/4/11 19:31
* @return
**/
public static void sort(int []arr){
//1.构建大顶堆
for(int i = arr.length/2-1;i >= 0;i--){
//从最后一个非叶子结点从下至上,从右至左调整结构
adjustHeap(arr,i,arr.length);
}
//2.调整堆结构+交换堆顶元素与末尾元素
for(int j = arr.length-1;j > 0;j--){
//将堆顶元素与末尾元素进行交换
swap(arr,0,j);
//重新对堆进行调整
adjustHeap(arr,0,j);
}
}
/**
* @Description 调整堆的结构
* @Author wayne
* @Param
* @Date 2019/4/11 19:30
* @return
**/
private static void adjustHeap(int []arr,int i,int length){
//先取出当前元素i
int temp = arr[i];
for(int k = i*2+1;k < length; k = k*2+1){ //从i结点的左子结点开始,也就是2i+1处开始
if( k+1 < length && arr[k] < arr[k+1]){//如果左子结点小于右子结点,k指向右子结点
k++;
}
if(arr[k] >temp){//如果子节点大于父节点,将子节点值赋给父节点(不用进行交换)
arr[i] = arr[k];
i = k;
}else{
break;
}
}
arr[i] = temp;//将temp值放到最终的位置
}
/**
* @Description
* @Author wayne 交换元素
* @Param
* @Date 2019/4/11 19:31
* @return
**/
private static void swap(int []arr,int a ,int b){
int temp=arr[a];
arr[a] = arr[b];
arr[b] = temp;
}
}
其实只要知道上面两张图的数据变化,堆排序就没啥难理解的了