zoukankan      html  css  js  c++  java
  • 堆(优先队列)

    问题:如何找到一串数据中最大的M个数或者最小的M个数?

    :可以构造一个包含M个数的堆或者直接将这串数据构造成一个堆

    大根堆:父节点大于等于两个子节点,可以使用数组构造堆,

    1、从下标为1的位置开始存储;第k个位置的父节点:k/2,子节点位置: 2k 和 2k+1

    2、从下标为0的位置开始存储,第k个位置的父节点:(k-1)/2,子节点位置:2k+1 和 2k+2

    通过上浮和下沉操作向堆添加元素和删除元素

      添加元素:把元素放到数组最后一位,再上浮到合适的位置;最多需要lgN次(N为元素个数)

    删除元素:数组的第一个元素和最后一个元素交换,然后将第一个元素下沉到合适的位置;最多需要2lgN次(每层两次)

    堆的实现

    import java.util.Arrays;
    
    public class MaxPQ<T extends Comparable<T>>{
        private static final int DEFAULT_INITIAL_CAPACITY = 11;
        private T[] arr; // 用一个数组从下标为1的位置开始存储,当前节点k的父节点为k/2,子节点为2k和2k+1
        private int N = 0;
    
        @SuppressWarnings("all")
        public MaxPQ(){
            arr = (T[]) new Comparable[DEFAULT_INITIAL_CAPACITY];
        }
    
        @SuppressWarnings("all")
        public MaxPQ(int MaxN){
            arr = (T[]) new Comparable[MaxN+1];
        }
        public void insert(T t){
            int i = size() + 1;
            if(i>=arr.length)
                arr = Arrays.copyOf(arr, size()*2);
            arr[++N] = t;
            swim(N);        // 每次将添加的元素插入到最后的位置,然后上浮到合适的位置
        }
    
        public T delMax(){
            T max = arr[1]; // 返回最大的元素,如果要返回最小的元素,只需要改变上浮和下沉的比较
            exch(1, N--);   // 与数组最后的元素交换,数组长度减1,然后将这个元素下沉到合适的位置
            arr[N+1] = null;
            sink(1);
            return max;
        }
    
        public int size(){
            return N;
        }
    
        public boolean isEmpty(){
            return size()==0;
        }
    
        public void swim(int k){
            // 上浮的时候与父节点(arr[k/2])比较,大于父节点就上浮
            while(k>1 && arr[k/2].compareTo(arr[k])<0){
                exch(k/2, k);
                k = k/2;
            }
        }
    
        public void sink(int k){
            while(2*k <= N){  
                int j = 2*k;  
                // 注意j在这一步迭代中要小于剩余元素个数,否则会空指针异常
                // 用较大的子节点(2k或者2k+1)和父节点k比较
                if(j<N && arr[j].compareTo(arr[j+1])<0) j++;
                // 如果父节点大于两个子节点,则不用交换,否则与较大的子节点交换
                if(arr[k].compareTo(arr[j])>0) break; 
                exch(k, j);
                k = 2*k;
            }
        }
    
        public void exch(int i, int j){
            T temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }
    
        public void printArr(){
            for(int i=1; i<=N; i++){
                System.out.print(arr[i] + "	");
            }
            System.out.println();
        }
    
        public static void main(String[] args){
            MaxPQ<String> arr = new MaxPQ<>(11);
            String[] strings = {"S","G","H","P","N","A","O","E","I","R","T","A"};
            for(String s: strings)
                arr.insert(s);
            arr.printArr();
            System.out.println("+++++++++");
            while(arr.size()!=0){
                arr.delMax();
                arr.printArr(); 
            }  
        }
    }
    View Code

    有一串很大的数据,需要找出k个最大的或者最小的数?

    大根堆:维护k个最小的数;如果加入的元素小于堆顶元素则替换堆顶元素,并下沉到合适位置

    小根堆:维护k个最大的数;如果加入的元素大于堆顶元素则替换堆顶元素,并下沉到合适位置,如果加入的元素小于堆顶的元素则抛弃

    java的优先队列 

  • 相关阅读:
    js 与或运算符 || && 妙用(great!!!)
    type of && undefined
    全新框架?微信小程序与React Native的异同之处
    JS-十五章(15.16)
    JS-第十三章
    ValueError: zero-size array to reduction operation maximum which has no identity
    time
    模块
    day8-函数
    day7-format字符串格式化
  • 原文地址:https://www.cnblogs.com/pineapple-chicken/p/14534022.html
Copyright © 2011-2022 走看看