具體思路:
用一個最大堆存放比中位數小(或等於)的元素,用一個最小堆存放比中位數大(或等於)的元素。這裏關鍵的方法是insert(),每當要插入一個元素時,根據判斷條件將它插入最大堆或是最小堆,並更新最大堆和最小堆,使得最大堆和最小堆中元素的個數之差不超過1,這樣中位數就是最大堆或最小堆的堆頂元素。當最大堆和最小堆中元素個數不同(個數相差爲1)時,元素個數多的那個堆的堆頂元素即爲中位數;如果兩者元素個數相同,那麼中位數可以是最大堆和最小堆的堆頂元素的值取平均。下面的程序代碼中,當兩者元素個數相同時,將最大堆的堆頂元素看做中位數。
插入(insert) (1)如果最大堆爲空,將元素插入最大堆;(2)如果最小堆爲空,將元素插入最小堆;(3)如果元素比最大堆的堆頂元素小且最大堆中元素個數不大於最小堆中元素個數,將元素插入最大堆;如果如果元素比最大堆的堆頂元素小但最大堆中元素個數大於最小堆中元素個數,那麼先把最大堆的堆頂元素插入最小堆,然後刪除最大堆的堆頂元素,最後把元素插入最大堆;(4)如果元素比最小堆的堆頂元素大且最小堆中元素個數不大於最大堆中元素個數,將元素插入最小堆;如果如果元素比最小堆的堆頂元素大但最小堆中元素個數大於最大堆中元素個數,那麼先把最小堆的堆頂元素插入最大堆,然後刪除最小堆的堆頂元素,最後把元素插入最小堆;(5)如果最大堆中元素個數小於最小堆中元素個數,將元素插入最大堆;否則將元素插入最大堆。
- package com.ldl.algorithms.Exercise;
-
- import com.ldl.algorithms.StdIn;
- import com.ldl.algorithms.StdOut;
-
- public class Midian<Key> {
- private MaxPQ max; //store items less than midian
- private MinPQ min; //store items larger than midian
-
- /**
- * Initialize max and min
- */
- public Midian(){
- max = new MaxPQ();
- min = new MinPQ();
- }
-
- /**
- * Is both max and min are empty?
- */
- public boolean isEmpty(){
- return max.isEmpty() && min.isEmpty();
- }
-
- /**
- * Add a new key to either max or min.
- */
- public void insert(Key k){
- if(max.isEmpty()) {
- max.insert(k);
- return;
- }
- if(min.isEmpty()){
- min.insert(k);
- return;
- }
- if(less(k, (Key)max.max())) {
- if(max.size() <= min.size()) max.insert(k);
- else {
- min.insert(max.delMax());
- max.insert(k);
- }
- }
- else if(less((Key)min.min(), k)){
- if(min.size() <= max.size()) min.insert(k);
- else{
- max.insert(min.delMin());
- min.insert(k);
- }
- }
- else{
- if(max.size() < min.size()) max.insert(k);
- else min.insert(k);
- }
- }
-
- /**
- * Return the midian key on max or min.
- * Throw an exception if both max and min empty.
- */
- public Key midian(){
- if (isEmpty()) throw new RuntimeException("Both max and min are underflow");
- if(max.size() < min.size()) return (Key)min.min();
- return (Key)max.max();
- }
-
- private boolean less(Key k1, Key k2){
- return ((Comparable)k1).compareTo(k2) < 0;
- }
-
- /**
- * A test client.
- */
- public static void main(String[] args){
- Midian midian = new Midian();
- while(!StdIn.isEmpty()){
- String item = StdIn.readString();
- if(!item.equals("-")) midian.insert(item);
- else if(!midian.isEmpty()) StdOut.print(midian.midian());
- }
- }
- }