堆排序

Posted no_one

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了堆排序相关的知识,希望对你有一定的参考价值。

1、堆的特点
  • 是完全二叉树:除了树的最后一层结点不需要是满的,其他的每一层从左到右都完全是满的。
  • 通常采用数组实现
  • 堆中的每一个结点都满足堆的条件,也就是说每一个结点的关键字都大于等于(或小于等于)这个结点的子节点的关键字
技术分享
堆节点的访问:
     对于给定的某个结点的下标 i,
  • 它的父节点的下标为floor((i-1) / 2)
  • 它的左子节点的下标为2 * i + 1
  • 它的右子节点的下标为2 * i + 2

 

堆排序算法思想

将待排序的序列构造成一个大顶堆。此时,整个序列的最大值就是堆顶的根节点。将其与堆数组的末尾元素交换,此时末尾元素就是最大值,然后将剩余的n-1个序列重新构造成一个堆,这样就会得到n个元素中的次最大值。如此反复执行,就能得到一个有序序列了。

/**
 * 时间复杂度O(NLogN), 空间复杂度O(1)
 * @author Wu
 *
 */
public class HeapSort {
    
    private static int[] arr = new int[]{1,0};
    public static void main(String[] args) {
        // 堆排
        heapSort(arr);
        // 打印排序后的数组
        print(arr);
    }
    
    private static void heapSort(int[] arr) {
        
        // 将待排序的序列构建成最大堆,从最后一个父节点开始
        for(int i = arr.length / 2 - 1; i >= 0; i--) {
            buildMaxHeapify(arr, i, arr.length);
        }
        
        // 逐步将每个最大值的根节点与末尾元素交换,并且再调整二叉树,使其成为大顶堆 
        for(int i = arr.length - 1; i >= 0; i--) {
            
            // 将堆顶记录和当前未经排序子序列的最后一个记录交换  
            int tmp = arr[0];  
            arr[0] = arr[i];  
            arr[i] = tmp;  
         
            buildMaxHeapify(arr, 0, i); // 交换之后,需要重新检查堆是否符合大顶堆,不符合则要调整  
        }
        
                
    }
    /**
     * 构建最大堆过程
     * @param arr    原数组
     * @param i    根节点序号
     * @param length    数组长度
     */
    private static void buildMaxHeapify(int[] arr, int i, int length) {
        int largerChild;
        int top = arr[i];
        while(i < length / 2) {            // 只要i不在堆的最底层,也就是它只要至少还有一个子节点,就一直循环
            int leftChild = 2 * i + 1;
            int rightChild = 2 * i + 2;
            
            // 找最大的子节(要考虑右子节点不存在的情况)
            if(rightChild < length && arr[rightChild] > arr[leftChild]) {
                largerChild = rightChild;
            } else {
                largerChild = leftChild;
            }
            
            // 交换根节点与子节点,使满足最大堆
            
            if(top >= arr[largerChild]) {
                break;
            }
            
            arr[i] = arr[largerChild];
            i = largerChild;
        }
        arr[i] = top;  
    }
    
    
    private static void print(int[] arr) {
        for(int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
        
    }

    
    
    
}

 

以上是关于堆排序的主要内容,如果未能解决你的问题,请参考以下文章

选择排序(简单选择排序堆排序的算法思想及代码实现)

排序--08---堆排序

python代码实现堆排序

算法-java代码实现堆排序

一文带你了解堆排序

堆排序