zoukankan      html  css  js  c++  java
  • 排序——堆排序

    堆结构:是一个完全二叉树

    i的左右结点分别为2 * i + 1 和 2 * i + 2,

    父结点:(i - 1)>>1

    构建大根堆heapInsert:每次添加进来的结点 i 找到它的父结点(i-1)>>2,若大于父结点,则交换,继续寻找此时父结点的父结点  

    调整大根堆heapIfy:将交换后的结点与其两个子结点进行比较(若小于他们)则与较大的子结点进行交换,然后继续向下寻找


     如果只是建立堆的过程, 时间复杂度为O(N)
     优先级队列结构, 就是堆结构

    public void HeapSort(Integer[] arrays){
            if(arrays == null || arrays.length == 0) return;
    
            for(int i = 1; i < arrays.length; i++){
                //从0~i位置调整成大根堆
                heapInsert(arrays, i);
            }
            for(int j = arrays.length - 1; j > 0;){
                swap(arrays, 0, j);
                heapIfy(arrays, --j, 0);
            }
        }
    
        //将一个结点加到当前大根堆,并且调整位置的过程
        public void heapInsert(Integer[] arrays, int index){
            while(index > 0 && arrays[index] > arrays[(index - 1) >> 1]){
                swap(arrays, index, (index - 1) >> 1);
                index = (index - 1) >> 1;
            }
        }
    
        //数组中某位置index出的值变小了,调整成大根堆的过程
        public void heapIfy(Integer[] arrays, int len, int index){
            int left = index * 2 + 1;
            while(left < len){
                //右孩子不越界,且右孩子比左孩子大,则前边成立,否则后边成立
                int max = left + 1 < len && (arrays[left + 1] > arrays[left]) ? left + 1: left;
                
                //判断最大的孩子与父结点的值谁大谁小,若父结点的值大,则退出,否则交换,继续向下进行比较
                max = arrays[index] > arrays[max] ? index : max;
                if(max == index) break;
                swap(arrays, index, max);
                index = max;
                left = index * 2 + 1;
            }
        }
    

      

    重点是构造大顶堆(或小顶堆)

    在构造过程中,要知道一个规律:起始点为1 -- len的数组中,

    i的左右结点分别为2 * i + 1 和 2 * i + 2,

    而换算在以0开始的数组中,

    i处的左右结点分别为2 * i - 1和2 * i

    堆排序中,是将大顶堆的最前边的是arrays[0]从后往前依次进行替换,将大顶堆的数值依次交换到后面去

    而且在构造大顶堆的时候,是从len/2开始,它的左右子结点分别为 2 * i 和2 * i + 1,其实在数组中是2 * i - 1和2 * i

    package sort;
    import static sort.PrintRes.swap;
    public class HeapSort {
        public void heapSort(Integer[] arrays){
            if(arrays.length == 0) return;
            //构造大顶堆
            int len = arrays.length;
            for(int i = len - 1; i > 0; i--){
                bigHeap(arrays, len--);
                if(arrays[0] > arrays[i]){
                    swap(arrays, 0, i);
                }
            }
            //将大顶堆的数值与数组的最后一个数交换,继续构造大顶堆
        }
    
        public void bigHeap(Integer[] arrays, int len){
            for(int i = len/2; i >= 1; i--){
                int max;
                if(i * 2 >= len) max = i * 2 - 1;
                else{
                    max = arrays[i * 2 - 1] > arrays[i * 2] ? i * 2 : i * 2 + 1;
                }
                if(arrays[i - 1] < arrays[max - 1]) swap(arrays, i - 1, max - 1);
            }
        }
    }
    

      

     应用:剑指offer——最小的K个数

  • 相关阅读:
    如何设置Xcode模拟器地图的当前位置
    序列化框架MJExtension详解 + iOS ORM框架
    ios 容错处理JKDataHelper和AvoidCrash
    2017.5.3最新申请公司开发者账号整个流程(包括邓白氏申请详细流程带截图)
    详细分享UICollectionView的自定义布局(瀑布流, 线性, 圆形...)
    Mac系统安装和配置tomcat步骤详解
    Mac下intellij IDEA新建javaweb项目
    Apple Mach-O Linker Warning 警告解决办法
    项目适配iOS9遇到的一些问题及解决办法(更新两个小问题)
    iOS 中 延迟操作四种方式
  • 原文地址:https://www.cnblogs.com/SkyeAngel/p/8666570.html
Copyright © 2011-2022 走看看