使用优先级队列计算中位数

时间:2012-07-25 22:34:00

标签: java collections

我正在为课程相关课程做这个作业,我是Java和DS和Algo的新手。我不会在这里粘贴我的全部代码。但下面是我面临的相关代码问题。

因此,要检索我使用PriorityQueueComparator接口的中位数。从下面的函数我试图制作两个PriorityQueue,例如对于21个元素,hLow优先级队列有11个最小元素,hHigh有10个最高元素。

public static void addToStream (int k) {
    hLow.add (k);
    if (hLow.size() > (hHigh.size() + 1)) {
        hHigh.add(hLow.poll());
    }
}

我为hLow编写的比较器函数是

hLComp = new Comparator <Integer> () {
        public int compare (Integer o1, Integer o2) {
            return o1.compareTo(o2);
        }   
    };

hHigh

hHComp = new Comparator <Integer> () {
        public int compare (Integer o1, Integer o2) {
            return -o1.compareTo(o2);
        }   
    };

我面临的问题是那个

hHigh.add(hLow.poll()) 

检索错误的值。例如,如果第一个值是3000然后那是中位数,但是当第二个值进入时,例如是6000.然后代码进入if条件,之后hHigh.peek显示3000和{{1} }显示6000.这与我的期望相反。

3 个答案:

答案 0 :(得分:1)

这是一个完整的类,其中包含查找中位数的示例。

public class Median {

static PriorityQueue<Integer> hHigh  = new PriorityQueue<Integer>(100, 
        new Comparator<Integer>() {
    public int compare (Integer o1, Integer o2) {
        return o1.compareTo(o2);
    }
});

static PriorityQueue<Integer> hLow  = new PriorityQueue<Integer>(100, 
        new Comparator<Integer>() {
    public int compare (Integer o1, Integer o2) {
        return -o1.compareTo(o2);
    }
});

public static void addToStream (int k) {
    if (hHigh.size() == 0 || k > hHigh.peek()){
        hHigh.add(k);
    }

    else {
        hLow.add(k);
    }

    if (hLow.size() > (hHigh.size() + 1)) {
        hHigh.add(hLow.poll());
    }
    if (hHigh.size() > hLow.size()){
        hLow.add(hHigh.poll()); 
    }
}

public static void main(String[] args) {
    addToStream(3104);
    addToStream(6185);
    addToStream(7818);
    addToStream(2106);
    addToStream(5480);
    System.out.println(hLow.peek());
}

}

此程序打印出:5480

答案 1 :(得分:1)

以上方法是错误的。试试5 4 3你会看到。 该算法需要基本情况​​。这里有很好的解释:

Find running median from a stream of integers

答案 2 :(得分:0)

每个队列中的值将按照您实现比较器的方式进行分类。 你实现的方式是添加函数,你只需要一个hHow而不是hHigh中的一个。

如果要将较大的一半保留在一个队列中而将另一个保留在第二个队列中,则需要比较每个队列头部的值。 根据结果​​,您可能需要在队列之间进行交换,就像您输入的数字一样。

尝试使用add函数:

首先,您需要将hLow比较器分配给hHigh,反之亦然。 然后在添加值后,hLow.peek()会给出中位数。

public static void addToStream (int k) {
if (hHigh.size() == 0 || k > hHigh.peek()){
    hHigh.add(k);
}

else {
    hLow.add(k);
}

if (hLow.size() > (hHigh.size() + 1)) {
    hHigh.add(hLow.poll());
}
if (hHigh.size() > hLow.size(){
    hLow.add(hHigh.poll()); 
}

}