堆排序实现

简介: 堆排序实现

公众号merlinsea


  • 堆的介绍
  • 堆是一种数据结构,其底层实现是一个完全二叉树,这个完全二叉树满足:任何一个非叶子节点的值都不大于(或者不小于)其左右孩子节点的值。若保证父节点的值大于等于孩子节点的值则称之为大根堆,若保证父节点的值小于等于其孩子节点的值则称之为小根堆

640.png

  • 堆排序的介绍
  • 根据堆堆定义可以知道,堆这棵完全二叉树的根节点是整棵树中的最大值(或者最小值),因此可以将根节点和最后一个节点交换位置,这样我们可以知道有序序列就增多一位,无序序列就减少一位,然后将无序序列重新调整为一个堆,不断重复这个过程,我们就得到了堆排序。
  • 堆排序的本质依旧是选择类排序,但和简单选择排序相比,我们每次选择最值的时间复杂度是O(logn)
  • 堆排序(从小到大排序为例)的流程如下:
  • 将输入的初始序列建立为一个大根堆
  • 将堆顶元素和最后一个元素交换位置
  • 将无序序列重新调整为一个堆
  • 重复第2步骤和第3步骤,直到整个序列有序。


640.png


public class Main {
    public static void main(String[] args) {
        int[] array = new int[]{7,29,32,58,11,45,35,23,45,49};
        System.out.println("元素序列");
        for(int k : array){
            System.out.printf("%d \t",k);
        }
        System.out.println();
        creadMaxHeap(array);
        System.out.println("初始化为大根堆");
        for(int k : array){
            System.out.printf("%d \t",k);
        }
        System.out.println();
        heapSort(array);
        System.out.println("堆排序后");
        for(int k : array){
            System.out.printf("%d \t",k);
        }
        System.out.println();
    }
    //堆排序
    public static void heapSort(int[] arr){
        //无序序列的最后的位置
        int lastIdx = arr.length - 1;
        while(lastIdx>0){
            // 交换
            int temp = arr[0];
            arr[0] = arr[lastIdx];
            arr[lastIdx] = temp;
            lastIdx--;
            //调整堆
            int lastPar = (lastIdx+1)/2-1;
            int cur = 0;
            while(cur<=lastPar){
                //说明cur 有孩子节点
                int maxChild = cur*2+1;
                // 没次调整一个,无序序列就少一个,那么lastIdx就减少1
                if(maxChild+1<=lastIdx && arr[maxChild]<arr[maxChild+1]){
                    maxChild = maxChild + 1;
                }
                if(arr[maxChild]>arr[cur]) {
                    //向下调整
                    temp = arr[cur];
                    arr[cur] = arr[maxChild];
                    arr[maxChild] = temp;
                    cur = maxChild;
                }else{
                    break;
                }
            }
        }
    }
    //建立大根堆
    public static void creadMaxHeap(int[] arr){
        int lastPar = arr.length /2 - 1;
        int cur = lastPar;
        while(cur>=0){
            int par = cur;
            while(par<=lastPar) {
                // 假设孩子节点中最大值是左孩子
                int maxChild = par * 2 + 1;
                if (maxChild + 1 < arr.length && arr[maxChild + 1] > arr[maxChild]) {
                    //若有右孩子并且右孩子是孩子节点中更大的那个,移动maxChild
                    maxChild = maxChild + 1;
                }
                if (arr[maxChild] > arr[par]) {
                    //需要交换位置
                    int temp = arr[maxChild];
                    arr[maxChild] = arr[par];
                    arr[par] = temp;
                    //继续向下调整
                    par = maxChild;
                } else {
                    break;
                }
            }
            cur--;
        }
    }
}


  • 堆排序的性能分析
  • 算法时间复杂度:堆排序的时间主要耗费在将无序序列部分调整为堆的过程,每次调整需要比较的最大次数是完全二叉树的高度,因此堆排序的时间复杂度的上限是O(nlogn)
  • 算法空间复杂度:由于堆排序是基于原始输入的数组进行排序的,因此空间复杂度是O(1)
  • 算法稳定性分析:堆排序是不稳定排序。


算法训练营永久刷题班元旦优惠价,超低价格永久刷题。加入我们可以一起备战明年的春招笔试,快来参加吧~


算法训练营元旦福利

奔跑的小梁,公众号:梁霖编程工具库leetcode刷题直播教学,手把手带你刷题,元旦价格优惠通知,超低价格永久刷题


相关文章
|
2月前
|
存储 搜索推荐 算法
堆排序讲解
堆排序讲解
22 4
|
5月前
|
存储
|
6月前
|
分布式计算 搜索推荐 Java
堆排序就是这么容易
堆排序就是这么容易
49 0
|
7月前
|
算法 搜索推荐 Java
选择排序 - 堆排序
选择排序 - 堆排序
选择排序 - 堆排序
|
7月前
|
搜索推荐 算法
【排序算法】堆排序详解与实现
【排序算法】堆排序详解与实现
|
7月前
|
搜索推荐 算法 C++
C++堆排序的实现
C++堆排序的实现
|
7月前
选择排序与堆排序
选择排序与堆排序
42 0
|
7月前
|
算法 搜索推荐 索引
堆排序详细解读
堆排序详细解读
64 0
|
算法 索引 搜索推荐
|
存储 算法 搜索推荐
排序算法——堆排序
排序算法——堆排序