zoukankan      html  css  js  c++  java
  • 堆排序获取TopN

    package com.zjl.tool.sort;
    
    /**
     * 求前面的最大K个 解决方案:小根堆 (数据量比较大(特别是大到内存不可以容纳)时,偏向于采用堆)
     * @author 张恩备
     * @date 2016-11-25 下午12:15:36
     */
    public class TopNByHeap {
        /**
         * 待排序列(R1,R2,...,Rk,...Rn)看作是完全二叉树,通过比较、交换,父节点和孩子节点的值,
         * 使得对于任意元素Rk(k<=n/2),满足Rk>=R(2k),Rk>=R(2k+1)
         * @param arr    数组对象
         * @param start    数组的开始下标
         * @param end    数组的结束下标
         */
        private static void HeapAdjust(int[] arr, int start, int end) {
            //当下标为start的元素有孩子元素时
            while(start <= end/2) {
                //left和right分别为左右孩子元素的下标,max为左右孩子中值较小的孩子的元素下标
                int left = 2 * start+1;
                int right = 2 * start+2;
                int min = 0;
                
                //如果既有左孩子,又有右孩子
                if(left < end&&right <= end) {
                    //如果左孩子小于右孩子的值,max = right,否则为max = left
                    if(arr[left] <= arr[right])
                        min = left;
                    else
                        min = right;
                }
                //如果只有左孩子,没有右孩子,max值为left
                if(left <= end&&right > end) {
                    min = left;
                }
                //如果没有孩子,则表明到了完全二叉树的叶子节点
                if(left > end) {
                    break;
                }
                
                //如果当前节点值小于两孩子中的值较大者,那么将当前节点值与max交换
                if(arr[start] > arr[min]){
                    int tmp = arr[start];
                    arr[start] = arr[min];
                    arr[min] = tmp;
                }
                //当前节点向孩子节点迭代
                start = min;
            }
        }
        
        /**
         * 创建k个节点的小根堆
         * 
         * @param a
         * @param k
         * @return
         */
        static int[] createHeap(int a[], int k) {
            int[] result = new int[k];
            for (int i = 0; i < k; i++) {
                result[i] = a[i];
            }
            //由最后一个非叶子节点,向根节点迭代,创建最大堆,数组中的最大值将被移动到根节点
            for(int start = k-1/2;start >= 0;start--) {
                HeapAdjust(result, start, k-1);
            }
            return result;
    
        }
    
        static void insert(int a[], int value, int k) {
            //当输入元素的值value大于堆的根元素值时,则将堆的根元素的值赋值为输入元素的值value
             a[0]=value;
             //将改变后的堆重新k个节点的生成小根堆
             for(int start = k-1/2;start >= 0;start--) {
                    HeapAdjust(a, start, k-1);
                }
        }
    
        static int[] getTopKByHeap(int input[], int k) {
            int heap[] = createHeap(input, k);
            for(int i=k;i<input.length;i++){
                //当input[i]值大于堆的根元素值时,将input[i]插入到堆中
                if(input[i]>heap[0]){
                    insert(heap, input[i], k);
                }
            }
            
            //将小根堆降序排列
            while(k-1 > 0){
                //交换arr[0]和arr[k-1]的值
                int tmp = heap[0];
                heap[0] = heap[k-1];
                heap[k-1] = tmp;
                
                //待排序堆的范围变为依次减小,最后剩下一个元素时结束
                 //执行完这一步,根元素的值变为整个待序列中的最小值
                HeapAdjust(heap, 0, k-2);
                
                k--;
            }
            return heap;
        }
    
        public static void main(String[] args) {
            int a[] = {40,55,49,73,12,27,98,81,64,36,78};
            //获取top3
            int result[] = getTopKByHeap(a, 3);
            for (int temp : result) {
                System.out.print(temp + " ");
            }
        }
    }
  • 相关阅读:
    CSRF
    PHP XXE漏洞
    jumpserver安装与部署
    ELK
    docker pull下来的镜像放哪儿了?
    MobSF 框架安装使用部署
    加密流量分析
    Pόlya定理-学习笔记
    所有区间异或的和的 一个加强
    计算一个序列有多少个不同的01子序列
  • 原文地址:https://www.cnblogs.com/huanongying/p/7622459.html
Copyright © 2011-2022 走看看