按照此处的回答https://stackoverflow.com/a/10931091/1311773,我试图实现两个堆,以便我可以计算出正在运行的中位数。
我对堆不熟悉,不知道从哪里开始实现这里描述的功能。 http://programmingpraxis.com/2012/05/29/streaming-median/
我的目标是创建一个小型测试程序,有效地计算运行中位数,因此随着列表的增长,中位数不需要从头开始重新计算。使用两堆,我应该能够做到,我对如何开始实现它感到不满。
对此有任何建议将不胜感激。
答案 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>
>;
为了实现流中值算法,该方法类似于:
然后,中位数是较大堆的顶部,或两堆顶部的平均值。
如果您认为需要手动管理堆,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;
}
}