二叉堆,堆排序,STL優先隊列的底層實現,劍指offer數據流中的中位數

一.

  • 下圖是從數組爲0下標開始計算的。
    這裏寫圖片描述

  • 下圖是從數組爲1下標開始計算的。引自《STL源碼剖析》 p173
    這裏寫圖片描述



  • 64.數據流中的中位數。《劍指offer》 p286

如何得到一個數據流中的中位數?如果從數據流中讀出奇數個數值,那麼中位數就是所有數值排序之後位於中間的數值。如果從數據流中讀出偶數個數值,那麼中位數就是所有數值排序之後中間兩個數的平均值。

class Solution {
public:
    void Insert(int num)
    {
        if((max.size()+min.size()) % 2 == 0)   //數據總數目是偶數,將新的數據放入到最小堆中
        {
            if(!max.empty() && num < max[0])   //如果新插入的數據比最大堆的最大值要小,那麼就將新數據插入到最大堆中,並將最大堆的最大值彈出,放到最小堆中
            {
                max.push_back(num);
                push_heap(max.begin(),max.end(),less<int>());

                pop_heap(max.begin(),max.end(),less<int>());  //彈出最大堆的最大值
                num = max.back();
                max.pop_back();
            }

            min.push_back(num);
            push_heap(min.begin(),min.end(),greater<int>()); //組建最小堆

        }
        else   //數據總數目是奇數,將新數據放入到最大堆中
        {
            if(!min.empty()&&num > min[0])  //新插入的數據比最小堆的最小值還要大,那麼就將新插入的數據放入最小堆中,並將最小堆的最小值彈出,放入最大堆中
            {
                min.push_back(num);
                push_heap(min.begin(),min.end(),greater<int>());

                pop_heap(min.begin(),min.end(),greater<int>());  //彈出最小堆最小值
                num = min.back();
                min.pop_back();
            }    

            max.push_back(num);
            push_heap(max.begin(),max.end(),less<int>());

        }
    }

    double GetMedian()
    { 
        int size = max.size()+min.size();
        if(size == 0)
            return 0;
        double res = 0;
        if(size % 2 == 1)
        {
            /*
           if(min.empty())
                res = max[0];

            if(max.empty())
                res = min[0];*/            
            res = min[0];  //當只有一個元素,不需要判斷是最大堆還是最小堆,因爲一個數是奇數,一定是放到最小堆中。
        }
        else
           res = (max[0]+min[0])/2;

        return res;
    }

    vector<double> max; //最大堆  //***涉及到浮點運算,原始數據存儲用double
    vector<double> min; //最小堆
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章