数据流中的中位数

来源:互联网 发布:java运行jar包中的类 编辑:程序博客网 时间:2024/06/14 02:43

问题:如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有值排序之后位于中间的数值。如果数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。

 分析:下面总结使用了没有排序的数组、排序的数组、排序的链表、二叉搜索树、AVL数、最大堆和最小堆几种不同的数据结构的时间复杂度。

思路:综合考虑用堆实现,考虑将数据序列从中间开始分为两个部分,左边部分使用大根堆表示,右边部分使用小根堆存储。每遍历一个数据,计数器count增加1,当count是偶数时,将数据插入小根堆;当count是奇数时,将数据插入大根堆。当所有数据遍历插入完成后(时间复杂度为O(logn),如果count最后为偶数,则中位数为大根堆堆顶元素和小根堆堆顶元素和的一半;如果count最后为奇数,则中位数为小根堆堆顶元素。

详细的实现代码如下:
template<typename T> class DynamicArray{public:    void Insert(T num)    {        if(((min.size() + max.size()) & 1) == 0)        {            if(max.size() > 0 && num < max[0])            {                max.push_back(num);                push_heap(max.begin(), max.end(), less<T>());                num = max[0];                pop_heap(max.begin(), max.end(), less<T>());                max.pop_back();            }            min.push_back(num);            push_heap(min.begin(), min.end(), greater<T>());        }        else        {            if(min.size() > 0 && min[0] < num)            {                min.push_back(num);                push_heap(min.begin(), min.end(), greater<T>());                num = min[0];                pop_heap(min.begin(), min.end(), greater<T>());                min.pop_back();            }            max.push_back(num);            push_heap(max.begin(), max.end(), less<T>());        }    }//获得数据流的中位数    T GetMedian()    {         int size = min.size() + max.size();        if(size == 0)            throw exception("No numbers are available");        T median = 0;        if((size & 1) == 1)            median = min[0];        else            median = (min[0] + max[0]) / 2;        return median;    }private:    vector<T> min;    vector<T> max;};// ==================== Test Code ====================void Test(char* testName, DynamicArray<double>& numbers, double expected){    if(testName != NULL)        printf("%s begins: ", testName);    if(abs(numbers.GetMedian() - expected) < 0.0000001)        printf("Passed.\n");    else        printf("FAILED.\n");}int main(int argc, char* argv[]){    DynamicArray<double> numbers;    printf("Test1 begins: ");    try    {        numbers.GetMedian();        printf("FAILED.\n");    }    catch(exception e)    {        printf("Passed.\n");    }    numbers.Insert(5);    Test("Test2", numbers, 5);    numbers.Insert(2);    Test("Test3", numbers, 3.5);    numbers.Insert(3);    Test("Test4", numbers, 3);    numbers.Insert(4);    Test("Test6", numbers, 3.5);    numbers.Insert(1);    Test("Test5", numbers, 3);    numbers.Insert(6);    Test("Test7", numbers, 3.5);    numbers.Insert(7);    Test("Test8", numbers, 4);    numbers.Insert(0);    Test("Test9", numbers, 3.5);    numbers.Insert(8);    Test("Test10", numbers, 4);return 0;}



0 0
原创粉丝点击