Java 实现堆排序和topK排名、leastK排名

对于数据量比较大的情况,堆排序比较合适,而且堆排序每一轮可以找出当前数据中最大(大顶堆)或最小(小顶堆)的数,所以对于以上问题,用堆排序是不错的选择:比如王者荣耀上亿用户的排名
package ArrayAlgo;

import java.util.Arrays;

//堆排序和获取topK排名、获取leastK排名
public class HeapSort {

    public static void main(String[] args) {
        int a[] = {51, 46, 20, 18, 65, 97, 82, 30, 77, 50};
        //maxHeapSort(a);
        // minHeapSort(a);
        //System.out.println(Arrays.toString(a));
        int[] res = findTopK(a, 3);
        //int[] res=findLeastK(a,3);
        System.out.println(Arrays.toString(res));
    }

    //获取topK排名
    public static int[] findTopK(int[] array, int k) {
        int[] temp = new int[k];
        for (int i = 0; i < k; i++) {
            temp[i] = array[i];
        }
        for (int i = k / 2; i >= 0; i--) {
            adjustMinHeap(temp, i, k - 1);
        }
        for (int j = k; j < array.length; j++) {
            if (temp[0] < array[j]) {  //存在更大的数字
                temp[0] = array[j];
                adjustMinHeap(temp, 0, k - 1); //重新调整堆
            }
        }
        finalMaxSort(temp);
        return temp;
    }

    //获取leastK排名
    public static int[] findLeastK(int[] array, int k) {
        int[] temp = new int[k];
        for (int i = 0; i < k; i++) {
            temp[i] = array[i];
        }
        for (int i = k / 2; i >= 0; i--) {
            adjustMaxHeap(temp, i, k - 1);
        }
        for (int j = k; j < array.length; j++) {
            if (temp[0] > array[j]) {  //存在更小的数字
                temp[0] = array[j];
                adjustMaxHeap(temp, 0, k - 1); //重新调整堆
            }
        }
        finalMinSort(temp);
        return temp;
    }


    //取topK的最后k个数字的排序
    public static void finalMaxSort(int[] a) {
        int length = a.length;
        for (int i = length - 1; i >= 0; i--) {
            swap(a, 0, i);
            adjustMinHeap(a, 0, i - 1);
        }
    }

    //取leastK的最后k个数字的排序
    public static void finalMinSort(int[] a) {
        int length = a.length;
        for (int i = length - 1; i >= 0; i--) {
            swap(a, 0, i);
            adjustMaxHeap(a, 0, i - 1);
        }
    }

    //大顶堆排序
    public static void maxHeapSort(int[] a) {
        int length = a.length;
        for (int i = length / 2; i >= 0; i--) {//构建一个大顶堆
            adjustMaxHeap(a, i, length - 1);
        }
        for (int i = length - 1; i >= 0; i--) {
            swap(a, 0, i);
            adjustMaxHeap(a, 0, i - 1);
        }
    }

    //小顶堆排序
    public static void minHeapSort(int[] a) {
        int length = a.length;
        for (int i = length / 2; i >= 0; i--) {//构建一个小顶堆
            adjustMinHeap(a, i, length - 1);
        }
        for (int i = length - 1; i >= 0; i--) {
            swap(a, 0, i);
            adjustMinHeap(a, 0, i - 1);
        }
    }

    public static void swap(int[] a, int i, int j) {
        int temp = a[i];
        a[i] = a[j];
        a[j] = temp;
    }

    //大顶堆调整
    public static void adjustMaxHeap(int[] array, int start, int end) {
        int temp = array[start];
        int child = start*2 + 1;
        while (child <= end) {
            if (child+1 <= end && array[child + 1] > array[child]) {
                child++;
            }
            if (array[child] < temp) {  //如果所有的孩子节点都小于父节点,就结束循环
                break;
            }else {
                array[start] = array[child];
                start = child; //迭代
                child = child*2 + 1;
            }
        } //end while
        array[start] = temp;
    }

    //小顶堆调整
    public static void adjustMinHeap(int[] a, int start, int end) {
        int temp = a[start];
        int child = start * 2 + 1;
        while (child <= end) {
            if (child + 1 <= end && a[child] > a[child + 1]) {
                child++;
            }
            if (a[child] > temp) {
                break;
            } else {
                a[start] = a[child];
                start = child;
                child = child * 2 + 1;
            }
        }
        a[start] = temp;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值