zoukankan      html  css  js  c++  java
  • 排序算法---堆排序

    堆是一种特殊的数据结构,首先堆是一个完全二叉树,所有堆满足所有二叉树的特定,对于大顶堆,最大数应用再一位,所有如果向对一个数组排序,可以将堆顶和最后一个元素交换,之后再次调整堆,直到堆元素个数为1,所有堆排序算法很简单:

    1. 将数组构建成一个堆(生序:大顶堆,降序:小顶堆)

    2. 交换堆顶和最后一个元素

    3. 迭代1,2步,直到所有元素排序完成

    代码实现如下:

    package algorithm.sort;
    
    import java.util.Random;
    import java.util.concurrent.atomic.AtomicInteger;
    
    /**
     * 堆排序
     * 堆性值:
     * 大顶堆  a[i] >= a[i2+1] && a[i] >= a[i2+2]
     * 小顶堆  a[i] <= a[i2+1] && a[i] <= a[i2+2]
     * 先构建大顶堆或者小顶堆,之后交换堆顶和最后一个元素,在堆N-1个元素重新构建堆,直到堆有序
     * 时间复杂度O(nlogn)
     */
    public class HeapSort {
    
        public static AtomicInteger n = new AtomicInteger(0);
    
        public static void swatch(int[] arr, int l, int r) {
            int tmp = arr[l];
            arr[l] = arr[r];
            arr[r] = tmp;
        }
    
        /**
         * 构建大顶堆 算法实现:
         * 1. 从堆的最后一个非子节点开始(arr.length/2-1),直到第一个元素开始遍历
         * 2. 让非子节点和它的子节点比较,选取出最大值
         * 3. 更新最大值到当前非子节点
         * 4. 再次使用以上步骤,更新子节点,直到最后一个非子节点
         *
         * @param arr         需要构建的数组
         * @param parentIndex 当前处理的非子节点
         * @param endIndex    数组长度,该参数主要用于堆排序,构建堆其实不需要该参数
         */
        public static void adjuestHead(int[] arr, int parentIndex, int endIndex) {
            //保存当前节点
            int tmp = arr[parentIndex];
            // 非子节点第一个孩子
            int childIndex = parentIndex * 2 + 1;
            while (childIndex < endIndex) {
                // 判断是否有两个孩子
                if (childIndex + 1 < endIndex && arr[childIndex] < arr[childIndex + 1]) childIndex += 1;
                //如果父节点大于子节点,则直接退出
                if (tmp >= arr[childIndex]) break;
                arr[parentIndex] = arr[childIndex];
                //继续堆子节点调整
                parentIndex = childIndex;
                childIndex = childIndex * 2 + 1;
            }
            arr[parentIndex] = tmp;
        }
    
        public static void maxHeadHeap(int[] arr) {
            // 第一个非叶子节点,从下至上,从右至左
            for (int i = arr.length / 2 - 1; i >= 0; i--) {
                adjuestHead(arr, i, arr.length);
            }
        }
    
        public static void headSort(int[] arr) {
            //初始并构建大顶堆
            maxHeadHeap(arr);
    
            for (int index = arr.length - 1; index >= 0; index--) {
                //交换堆顶和最后一个元素
                swatch(arr, 0, index);
                //重新调整剩余堆元素
                adjuestHead(arr, 0, index);
            }
    
        }
    
        public static void main(String[] args) {
            int data_len = 100000;
            int[] data = new int[data_len];
            Random rd = new Random();
            for (int index = 0; index < data_len; ) {
                data[index++] = rd.nextInt(10000);
            }
            System.out.println("生成数据完成");
    //        showData(data);
            long start = System.currentTimeMillis();
            headSort(data);
            System.out.printf("堆排序算法	运行时间%dms
    ", (System.currentTimeMillis() - start));
            showData(data);
    
        }
    
        public static void showData(int[] data) {
            for (int item : data) {
                System.out.printf("%d,", item);
            }
            System.out.println();
        }
    }

    堆排序是一种选择排序,整体主要由构建初始堆+交换堆顶元素+重建堆组成,其中堆构建的时间复杂度O(n),交换并重建需要交换n-1次,重建堆过程,根据二叉树性值为nlogn,所以堆排序时间负责度一般认为是O(nlogn)

  • 相关阅读:
    switch_goto
    隐藏 窗口的整个 标题栏(包括右上角的关闭)
    asp的邦定表达式异常 <_ %_ = strParentid _%_>不能传到下个页面
    【收藏】default.rdp配置
    计算机网络中的性能指标
    当某个快捷键不能用时很可能是热键冲突
    java的FOR循环 打印三角形
    二进制 八进制 十进制 十六进制
    linux的vim编辑命令常用
    JIRA的备份
  • 原文地址:https://www.cnblogs.com/yunfeiqi/p/7942707.html
Copyright © 2011-2022 走看看