How to implement a Median-heap

后端 未结 6 1218
佛祖请我去吃肉
佛祖请我去吃肉 2020-12-04 07:50

Like a Max-heap and Min-heap, I want to implement a Median-heap to keep track of the median of a given set of integers. The API should have the following three functions:

6条回答
  •  一个人的身影
    2020-12-04 08:32

    Here is a java implementaion of a MedianHeap, developed with the help of above comocomocomocomo 's explanation .

    import java.util.Arrays;
    import java.util.Comparator;
    import java.util.PriorityQueue;
    import java.util.Scanner;
    
    /**
     *
     * @author BatmanLost
     */
    public class MedianHeap {
    
        //stores all the numbers less than the current median in a maxheap, i.e median is the maximum, at the root
        private PriorityQueue maxheap;
        //stores all the numbers greater than the current median in a minheap, i.e median is the minimum, at the root
        private PriorityQueue minheap;
    
        //comparators for PriorityQueue
        private static final maxHeapComparator myMaxHeapComparator = new maxHeapComparator();
        private static final minHeapComparator myMinHeapComparator = new minHeapComparator();
    
        /**
         * Comparator for the minHeap, smallest number has the highest priority, natural ordering
         */
        private static class minHeapComparator implements Comparator{
            @Override
            public int compare(Integer i, Integer j) {
                return i>j ? 1 : i==j ? 0 : -1 ;
            }
        }
    
        /**
         * Comparator for the maxHeap, largest number has the highest priority
         */
        private static  class maxHeapComparator implements Comparator{
            // opposite to minHeapComparator, invert the return values
            @Override
            public int compare(Integer i, Integer j) {
                return i>j ? -1 : i==j ? 0 : 1 ;
            }
        }
    
        /**
         * Constructor for a MedianHeap, to dynamically generate median.
         */
        public MedianHeap(){
            // initialize maxheap and minheap with appropriate comparators
            maxheap = new PriorityQueue(11,myMaxHeapComparator);
            minheap = new PriorityQueue(11,myMinHeapComparator);
        }
    
        /**
         * Returns empty if no median i.e, no input
         * @return
         */
        private boolean isEmpty(){
            return maxheap.size() == 0 && minheap.size() == 0 ;
        }
    
        /**
         * Inserts into MedianHeap to update the median accordingly
         * @param n
         */
        public void insert(int n){
            // initialize if empty
            if(isEmpty()){ minheap.add(n);}
            else{
                //add to the appropriate heap
                // if n is less than or equal to current median, add to maxheap
                if(Double.compare(n, median()) <= 0){maxheap.add(n);}
                // if n is greater than current median, add to min heap
                else{minheap.add(n);}
            }
            // fix the chaos, if any imbalance occurs in the heap sizes
            //i.e, absolute difference of sizes is greater than one.
            fixChaos();
        }
    
        /**
         * Re-balances the heap sizes
         */
        private void fixChaos(){
            //if sizes of heaps differ by 2, then it's a chaos, since median must be the middle element
            if( Math.abs( maxheap.size() - minheap.size()) > 1){
                //check which one is the culprit and take action by kicking out the root from culprit into victim
                if(maxheap.size() > minheap.size()){
                    minheap.add(maxheap.poll());
                }
                else{ maxheap.add(minheap.poll());}
            }
        }
        /**
         * returns the median of the numbers encountered so far
         * @return
         */
        public double median(){
            //if total size(no. of elements entered) is even, then median iss the average of the 2 middle elements
            //i.e, average of the root's of the heaps.
            if( maxheap.size() == minheap.size()) {
                return ((double)maxheap.peek() + (double)minheap.peek())/2 ;
            }
            //else median is middle element, i.e, root of the heap with one element more
            else if (maxheap.size() > minheap.size()){ return (double)maxheap.peek();}
            else{ return (double)minheap.peek();}
    
        }
        /**
         * String representation of the numbers and median
         * @return 
         */
        public String toString(){
            StringBuilder sb = new StringBuilder();
            sb.append("\n Median for the numbers : " );
            for(int i: maxheap){sb.append(" "+i); }
            for(int i: minheap){sb.append(" "+i); }
            sb.append(" is " + median()+"\n");
            return sb.toString();
        }
    
        /**
         * Adds all the array elements and returns the median.
         * @param array
         * @return
         */
        public double addArray(int[] array){
            for(int i=0; i

提交回复
热议问题