java -堆的实现及Top-k问题及第k 小的问题


堆的实现

package queuedemo;

import java.util.Arrays;

public class HeapDemp {

    public int[] elem;
    public int usedSize;

    public HeapDemp(){
        this.elem = new int[10];
    }

    public void adjustDown( int parent ,int len){
        int child = 2*parent+1;
        //说明有左孩子,child +1判断是否有右孩子
        while(child<len){
            if( child+1<len&&this.elem[child] < this.elem[child+1]){
                child++;
            }
            //child 下标一定是左右孩子的最大值
            if(this.elem[child] > this.elem[parent]){
                int tmp = this.elem[child];
                this.elem[child] = this.elem[parent];
                this.elem[parent] = tmp;
                parent = child;
                child  = 2*parent+1;
            }else{
                break;
            }
        }
    }

    public void adjustUp(int child){
        int parent = (child-1)/2;

        while(child >0){
            if(this.elem[child] > this.elem[parent]){
                int tmp = this.elem[child];
                this.elem[child] = this.elem[parent];
                this.elem[parent] = tmp;
                child = parent;
                parent =(child -1)/2;
            }else {
                break;
            }
        }
    }
    public void push(int val){
        if(isFull()){
            this.elem=
                    Arrays.copyOf(this.elem,2*this.elem.length);
        }
        this.elem[this.usedSize] = val;
        this.usedSize++;

        adjustUp(this.usedSize-1);
    }

    /**
     * 第一个和最后一个换,
     * 向下调整 0下标这棵树
     * @return
     */
    public int poll(){
        if(isEmpty()){
            throw new RuntimeException("队列为空");
        }
        int ret = this.elem[0];
        int tmp = this.elem[0];
        this.elem[0] = this.elem[this.usedSize-1];
        this.elem[this.usedSize-1] = tmp;
        this.usedSize--;
        adjustDown(0,this.usedSize);
        return ret;
    }

    public int peek(){
        if(isEmpty()){
            throw new RuntimeException("队列为空");
        }
        return this.elem[0];
    }

    public boolean isEmpty(){
        return this.usedSize == 0;
    }
    public boolean isFull(){
        return this.usedSize == this.elem.length;
    }
    public void createBigHeap( int[] array){
        for(int i = 0;i<array.length;i++){
            this.elem[i] = array[i];
            usedSize++;
        }
        //elem当中已经存放了元素
        for(int i = (this.usedSize-1-1)/2;i>=0;i--){
            adjustDown(i,this.usedSize);
        }
    }
    public void show(){
        for (int i = 0;i<this.usedSize;i++){
            System.out.print(this.elem[i] +" ");
        }
        System.out.println();
    }
}

``

堆实现Top-k问题

问题描述

有10 个元素 k = 3 要求前 k 个最大或者最小的元素

思路:要求前k个最小的元素建大堆
要求前K个最大的元素建小堆
时间复杂度nlog2k
前 k 个最大的元素

import java.util.Comparator;
import java.util.PriorityQueue;

public class class_Topk {
    public  static void Topk (int[] array, int k){
        // 大小为 k 的小堆
        PriorityQueue<Integer> minHeap = new PriorityQueue<>(k, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1 -o2;
            }
        });
        //2,遍历数组
        for (int i =0;i<array.length;i++){
            if (minHeap.size() < k){
                minHeap.offer(array[i]);
            }else{
                int top = minHeap.peek();
                if (array[i] > top){
                    minHeap.poll();
                    minHeap.offer(array[i]);
                }
            }
        }
        for (int i=0; i<k; i++){
            System.out.println(minHeap.poll());
        }
    }

    public static void main(String[] args) {
        int[] array = {27,15,19,18,28,34,65,49,25,37};
        Topk(array,3);
    }
}

运行结果
在这里插入图片描述
求前 K 个最小的元素只需将建堆的代码o1-o2 换成o2-o1
遍历代码中换成 array[i] < top

import java.util.Comparator;
import java.util.PriorityQueue;

public class class_Topk {
    public  static void Topk (int[] array, int k){
        // 大小为 k 的大堆
        PriorityQueue<Integer> minHeap = new PriorityQueue<>(k, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2 -o1;
            }
        });
        //2,遍历数组
        for (int i =0;i<array.length;i++){
            if (minHeap.size() < k){
                minHeap.offer(array[i]);
            }else{
                int top = minHeap.peek();
                if (array[i] < top){
                    minHeap.poll();
                    minHeap.offer(array[i]);
                }
            }
        }
        for (int i=0; i<k; i++){
            System.out.println(minHeap.poll());
        }
    }

    public static void main(String[] args) {
        int[] array = {27,15,19,18,28,34,65,49,25,37};
        Topk(array,3);
    }
}

运行结果 19 18 15


堆实现第k小的问题

有10 个元素 k = n 要求前第k 大或者第k小的元素

思路:

建立大小为 k的大堆,等数组遍历完成后,堆顶元素就是第k 小的元素

代码 与上面代码相似

import java.util.Comparator;
import java.util.PriorityQueue;

public class class_Topk {
    public  static void Topk (int[] array, int k){
        // 大小为 k 的小堆
        PriorityQueue<Integer> minHeap = new PriorityQueue<>(k, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2 -o1;
            }
        });
        //2,遍历数组
        for (int i =0;i<array.length;i++){
            if (minHeap.size() < k){
                minHeap.offer(array[i]);
            }else{
                int top = minHeap.peek();
                if (array[i] < top){
                    minHeap.poll();
                    minHeap.offer(array[i]);
                }
            }
        }

            System.out.println(minHeap.poll());

    }

    public static void main(String[] args) {
        int[] array = {27,15,19,18,28,34,65,49,25,37};
        Topk(array,3);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

we_opkn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值