解决TOPK问题与堆排序

目录

一、解决TOPK问题

方式一

方式二

二、堆排序

与建堆的区别

堆排序代码


一、解决TOPK问题

方式一

建立优先级队列,将所有数据放入其中,根据需求创建大根堆或小根堆,依次出队k个元素,放入结果集合中。

例如:找最小的k个数

因为优先级队列中默认建立的小根堆,不必修改比较方法。

代码如下:


import java.util.PriorityQueue;
public class TopK {
    public static int [] TopK1(int[] array,int k){
        //定义一个结果集
        int [] result=new int[k];
        //非空校验
        if(array.length==0){
            return result;
        }
        //创建优先级队列(小根堆)
        PriorityQueue queue=new PriorityQueue<>();
        for (int i=0;i

方式二

建立大根堆:若找最小的k个数,建立大根堆,先将数组前k个数放入队中,之后加入的每个数都与队顶元素作比较,比队顶元素小的和队顶元素做交换,否则不做处理,最后留在优先级队列中的k个数就是最小的k个值。

注:因为用优先级队列建立大根堆,所以需要改变默认的比较方法,用到的是comparator比较器,需要重写比较规则

建立小根堆:若找最大的k个数,建立小根堆,先将数组的前k个数放入队中,之后加入的每个数都与队顶元素作比较,比队顶元素大的和队顶元素做交换,否则不做处理,最后留在优先级队列中的k个数就是最大的k个值。

例如:找最小的k个值,建立大根堆。

public class TopK{

    public static int[] TopK(int[] array,int k) {
        //创建结果集
        int[] result = new int[k];
        //非空校验
        if (k <= 0) {
            return result;
        }
        //这里需要建立大根堆,修改比较规则
        //小根堆默认o1-o2,这里我们o2-o1实现大根堆
        PriorityQueue queue = new PriorityQueue<>(new Comparator() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2 - o1;
            }
        });
        for (int i=0;i

二、堆排序

与建堆的区别

堆排序是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。它是通过堆来进行选择数据。需要注意的是排升序要建小堆,排降序建大堆。最后输出的是有序数列。

建堆:大根堆中,只针对根节点比左右子树大(包括每一个子树都满足);小根堆中,只针对根节点比左右子树小(包括每一个子树都满足)。最后输出的不是有序数列。

堆排序代码

public class HeapSort {
    //建堆
    public static void createHeap(int[] array){
        for(int parent=(array.length-2)/2;parent>=0;parent--){
            shiftDown(array,parent,array.length);

        }
    }
    //向下调整
    private static void shiftDown(int[] array, int parent, int length) {
        // 找到左孩子节点
        int child = 2 * parent + 1;
        while (child < length) {
            // 判断有没有右孩子节点
            if (child + 1 < length) {
                // 如果有右孩子,取左右孩子节点中最大值的下标
                if (array[child + 1] > array[child]) {
                    //child始终在值最大的节点上
                    child++;
                }
            }
            // 孩子节点中最大的值与父节点的值比较
            if (array[child] <= array[parent]) {
                //小于等于父节点不做交换
                break;
            }
            // 大于父节点时,交换父子节点
            swap(array, parent, child);
            // 重置父子节点的下标
            parent = child;
            child = 2 * parent + 1;
        }
    }
    //交换父节点与子节点
    private static void swap(int[] array, int parent, int child) {
        int temp = array[parent];
        array[parent] = array[child];
        array[child] = temp;
    }
    //排序
    public static void sort (int [] array) {
        // 1.首先建堆
        createHeap(array);
        // 2. 确定终止下标
        //传进无序堆时,先把堆顶元素和最后一个元素做了交换,所以end应该在倒数第二的位置
        int end = array.length - 1;
        while (end >= 0) {
            // 3. 首尾交换
            swap(array, 0, end);
            // 4. 向下调整
            shiftDown(array, 0, end);
            // 5. 修正 end
            end--;
        }
    }

    public static void main(String[] args) {
        int [] array = { 27,15,19,18,28,34,65,49,25,37 };
        sort(array);
        System.out.println(Arrays.toString(array));
    }
}

你可能感兴趣的:(数据结构,java,算法,数据结构)