C ++实现堆中值函数

时间:2012-06-10 04:07:43

标签: c++ heap median

按照此处的回答https://stackoverflow.com/a/10931091/1311773,我试图实现两个堆,以便我可以计算出正在运行的中位数。

我对堆不熟悉,不知道从哪里开始实现这里描述的功能。 http://programmingpraxis.com/2012/05/29/streaming-median/

我的目标是创建一个小型测试程序,有效地计算运行中位数,因此随着列表的增长,中位数不需要从头开始重新计算。使用两堆,我应该能够做到,我对如何开始实现它感到不满。

对此有任何建议将不胜感激。

2 个答案:

答案 0 :(得分:4)

std::priority_queue模板提供堆的所有属性。恒定时间最大或最小提取(取决于项目的比较方式)和对数时间插入。它可以在<queue>头文件中找到。

默认情况下,priority_queue是最大堆。

int numbers[11] = { 0, 9, 3, 4, 8, 12, 2, 11, 10, 1, 5 };
std::priority_queue<int> myheap(numbers, numbers + 11);
std::cout << "biggest " << myheap.top() << std::endl; // 12
myheap.pop();
std::cout << "biggest " << myheap.top() << std::endl; // 11
myheap.push(6);
std::cout << "biggest " << myheap.top() << std::endl; // 11
myheap.push(13);
std::cout << "biggest " << myheap.top() << std::endl; // 13

以下是如何创建min-heap的示例:

std::priority_queue<
    int,
    std::priority_queue<int>::container_type,
    std::greater<int>
>;

为了实现流中值算法,该方法类似于:

  • 为小于中位数的项目创建最大堆
  • 为大于中位数的项目创建最小堆
  • 将新项目推入堆中
    • 决定将它推入哪个堆,并推送到那里
    • 如果其中一个堆的大小比另一个堆大1以上,则弹出较大的堆,并将该元素放入较小的堆中

然后,中位数是较大堆的顶部,或两堆顶部的平均值。

如果您认为需要手动管理堆,C++提供了允许您在自己的随机访问数据结构上执行此操作的算法。

  • std::make_heap - 堆积由迭代器端点
  • 指定的区域
  • std::push_heap - 假设第一个N-1个元素已经是一个堆,并将第N个元素放入堆中
  • std::pop_heap - 将区域中的第一个元素放入最后一个位置,然后重新定义该区域,但保留最后一个元素

答案 1 :(得分:0)

我想这会有所帮助。谢谢。

    #include<cstdio>
    #include<iostream>
    #include<queue>
    #include <vector>         
    #include <functional>

    typedef priority_queue<unsigned int> type_H_low;
    typedef priority_queue<unsigned int, std::vector<unsigned int>, std::greater<unsigned int> > type_H_high;

    size_t signum(int left, int right) {
        if (left == right){
            return 0;
        }
        return (left < right)?-1:1;
    }

    void get_median( unsigned int x_i, unsigned int &m, type_H_low *l, type_H_high *r) {

        switch (signum( l->size(), r->size() )) {
        case 1: // There are more elements in left (max) heap
            if (x_i < m) {
                r->push(l->top());
                l->pop();
                l->push(x_i);
            } else {
                r->push(x_i);
            }
            break;

        case 0: // The left and right heaps contain same number of elements
            if (x_i < m){
                l->push(x_i);
            } else {
                r->push(x_i);
            }
            break;

        case -1: // There are more elements in right (min) heap
            if (x_i < m){
                l->push(x_i);
            } else {
                l->push(r->top());
                r->pop();
                r->push(x_i);
            }
            break;
        }

        if (l->size() == r->size()){
            m = l->top();
        } else if (l->size() > r->size()){
            m = l->top();
        } else {
            m = r->top();
        }

        return;
    }

    void print_median(vector<unsigned int> v) {
        unsigned int median = 0;
        long int sum = 0;
        type_H_low  H_low;
        type_H_high H_high;

        for (vector<unsigned int>::iterator x_i = v.begin(); x_i != v.end(); x_i++) {
            get_median(*x_i, median, &H_low, &H_high);
            std::cout << median << std::endl;
        }
    }