• 堆排序


    堆排序

    堆排序时间复杂度为O(nlgn),且具有空间原址性,只需要常数个额外的元素空间存储临时数据。但堆排序是不稳定的算法,即对相等的两个元素,排序后不能保证他们的顺序与原始数据的顺序相同。

    1.堆

    堆是一个数组,可以把它看成一个近似的完全二叉树。树上的每一个结点对应数组中的一个元素,除最底层外,该树是完全充满的,而且是从左向右填充。
    堆数组有两个和堆排序相关的重要属性,数据元素的个数(length)和堆元素(heapSize)。可以理解为数组中只有一部分数据用来表示当前堆,因此 0 <= heapSize <= length。
    编程时,堆的根节点在数组中的索引值为0。对给定的某个节点的索引i,其父结点、左孩子和右孩子可以计算得出:
      parent(i) = (i - 1) >> 1;
      left(i) = (i << 1) + 1;
      right(i) = (i << 1) + 2;
    堆又分为最大堆和最小堆。在最大堆中,根节点的值不小于它的任意一个子节点,即最大元素存在根节点中。在最小堆中,根节点不大于它的任意一个子节点,即最小元素存在根节点中。

    2.维护堆的性质

    维护堆的性质是维护最大堆或最小堆的重要过程,维护最大堆或最小堆需要多次使用此方法。以最大堆为例,其算法如下:
      maxHeapify(a, i, heapSize)
        l = left(i);
        r = right(i);
        largest = i;
        if l < heapSize and a[largest] < a[l]
          largest = l;
        if r < heapSize and a[largest] < a[r]
          largest = r;
        if largest != i
          exchange(a[largest], a[i])
          maxHeapify(a, largest, heapSize)
    程序中a[i],a[l],a[r]中选出最大的,并将其下标存储在largest中。如果a[i]是最大的,那么以i为根的结点的子树已经是最大堆。否则,最大元素是i的某个子结点,则交换a[i]与a[largest]的值,从而使i及其孩子满足最大堆的性质。在交换后,下标为largest的结点的值是原来的a[i],于是以该结点为根的子树有可能违反最大堆的性质,需要对该子树递归调用maxHeapify方法。

    3.建堆

    建堆即建立最大堆或最小堆。需要用到maxHeapify方法。其算法如下
      buildMaxHeap(a)
        heapSize = a.length;
        for i = (a.length >> 2) downto 0
          maxHeapify(a, i, heapSize)

    4.堆排序算法

    (1)利用buildMaxHeap将输入的数组建立为最大堆
    (2)因为最大堆中的第一个元素为最大值,因此可以把它与最后一个位置交换,这时候最大值即被排到最后
    (3)但由于第一个元素改变,需要重新维护堆的性质,此时最后一个元素已排好序,去掉最后一个元素(heapSize减1)再次对第一个元素维护堆的性质即可
    (4)反复执行过程(2)~(3),直到第二个元素,就完成了堆排序。
      sort(a)
        buildMaxHeap(a)
        for i = a.length - 1 downto 1
          exchange(a[0], a[i])
          maxHeapify(a, 0, i)

    java算法实现

    package com.diysoul.algorithm.sort;
    
    import java.util.Random;
    
    public class HeapSort {
    
        public static void sort(int[] a) {
            buildMaxHeap(a);
            for (int i = a.length - 1; i > 0; i--) {
                int temp = a[0];
                a[0] = a[i];
                a[i] = temp;
                maxHeapify(a, 0, i);
            }
        }
    
        public static void buildMaxHeap(int[] a) {
            int heapSize = a.length;
            for (int i = a.length >>> 1; i >= 0; i--) {
                maxHeapify(a, i, heapSize);
            }
        }
    
        public static void maxHeapify(int[] a, int i, int heapSize) {
            int l = (i << 1) + 1;
            int r = (i << 1) + 2;
            int largest = i;
            if (l < heapSize && a[largest] < a[l]) {
                largest = l;
            }
            if (r < heapSize && a[largest] < a[r]) {
                largest = r;
            }
            if (largest != i) {
                int temp = a[i];
                a[i] = a[largest];
                a[largest] = temp;
    
                // print(a);
                maxHeapify(a, largest, heapSize);
            }
        }
    
        public static void main(String[] args) {
            int maxSize = 1000;
            int min = 0;
            int max = 1000;
            Random random = new Random();
    
            int[] a = new int[maxSize];
            for (int i = 0; i < a.length; i++) {
                a[i] = random.nextInt(max - min) + min;
            }
            print(a);
            sort(a);
            print(a);
            checkSort(a);
        }
    
        private static void checkSort(int[] array) {
            if (array == null || array.length == 0)
                return;
            for (int i = 1; i < array.length; i++) {
                if (array[i - 1] > array[i]) {
                    System.out.println("Error! Array is not sorted in index " + i);
                    break;
                }
            }
        }
    
        private static void print(int[] array) {
            if (array == null || array.length == 0)
                return;
            System.out.print("heap sort array(" + array.length + "): ");
            int i = 0;
            for (; i < array.length - 1; i++) {
                System.out.print(array[i] + ", ");
            }
            System.out.println(array[i]);
        }
    }
  • 相关阅读:
    RTP 控制协议
    非关系型数据库
    关系型数据库
    处理海量数据
    处理大并发
    C++ 模板偏特化-来自STL的思考
    C++详解new/delete
    二分算法来相会
    计算机网络知识点总结
    C++字符串类型转换
  • 原文地址:https://www.cnblogs.com/diysoul/p/5671134.html
Copyright © 2020-2023  润新知