您的位置:首页 > Web前端

二叉堆,堆排序,STL优先队列的底层实现,剑指offer数据流中的中位数

2017-08-14 11:06 651 查看
一.

下图是从数组为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; //最小堆
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: