题目描述
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。
分析
使用两个堆排数组,一个最大堆(前半段数据),一个最小堆(后半段数据)。
两个堆总共只有两种情况:
1、最大堆和最小堆数量相等(此时返回两个堆顶数目的相加平均)
2、最小堆数量多一个(返回最小堆顶元素)
如果新来的数字大于最小堆堆顶(属于后半段),那么塞入后半段数组
如果新来的属于前半段,塞入前半段数组
如果发现两边数目不均衡(最小堆-最大堆数目 超过1),则将进行最小堆顶元素给到最大堆,并且调整两个堆
代码实现
vector<int>min_half; // 最大堆
vector<int>max_half; // 最小堆
void Insert(int num)
{
if(min_half.size()<=0){
min_half.push_back(num);
return;
}
if(max_half.size()<=0){
max_half.push_back(num);
if(max_half[0]<min_half[0])swap(max_half[0],min_half[0]);
return;
}
if(min_half.size()==max_half.size()){
if(num>min_half[0]){
min_half.push_back( min(num,max_half[0]));
max_half[0]=max(num,max_half[0]);
HeapAdjustMax(min_half,0,min_half.size()-1);
HeapAdjustMin(max_half,0,max_half.size()-1);
}
else{
min_half.push_back(num);
HeapAdjustMax(min_half,0,min_half.size()-1);
}
}
else{
if(num>min_half[0]){
max_half.push_back(num);
HeapAdjustMin(max_half,0,max_half.size()-1);
}
else{
max_half.push_back( max(num,min_half[0]));
min_half[0]=min(num,max_half[0]);
HeapAdjustMax(min_half,0,min_half.size()-1);
HeapAdjustMin(max_half,0,max_half.size()-1);
}
}
}
double GetMedian()
{
if(min_half.size()==max_half.size()+1){
return min_half[0];
}
else
return 0.5*min_half[0]+0.5*max_half[0];
}
void HeapAdjustMax(vector<int>&a,int start,int end){
if(start>=end)
return ;
for(int i =end;i>=start;i--){
int left = 2*i+1;
int right= 2*i+2;
if(left<=end){
if(right<=end){
if(a[right]>a[left] && a[right]>a[i])
swap(a[i],a[right]);
else if(a[left]>a[i] && a[left]>a[right])
swap(a[i],a[left]);
}
else
if(a[left]>a[i])
swap(a[i],a[left]);
}
}
}
void HeapAdjustMin(vector<int>&a,int start,int end){
if(start>=end)
return ;
for(int i =end;i>=start;i--){
int left = 2*i+1;
int right= 2*i+2;
if(left<=end){
if(right<=end){
if(a[right]<a[left] && a[right]<a[i])
swap(a[i],a[right]);
else if(a[left]<a[i] && a[left]<a[right])
swap(a[i],a[left]);
}
else
if(a[left]<a[i])
swap(a[i],a[left]);
}
}
}
vector<int>max_half; // 最小堆
void Insert(int num)
{
if(min_half.size()<=0){
min_half.push_back(num);
return;
}
if(max_half.size()<=0){
max_half.push_back(num);
if(max_half[0]<min_half[0])swap(max_half[0],min_half[0]);
return;
}
if(min_half.size()==max_half.size()){
if(num>min_half[0]){
min_half.push_back( min(num,max_half[0]));
max_half[0]=max(num,max_half[0]);
HeapAdjustMax(min_half,0,min_half.size()-1);
HeapAdjustMin(max_half,0,max_half.size()-1);
}
else{
min_half.push_back(num);
HeapAdjustMax(min_half,0,min_half.size()-1);
}
}
else{
if(num>min_half[0]){
max_half.push_back(num);
HeapAdjustMin(max_half,0,max_half.size()-1);
}
else{
max_half.push_back( max(num,min_half[0]));
min_half[0]=min(num,max_half[0]);
HeapAdjustMax(min_half,0,min_half.size()-1);
HeapAdjustMin(max_half,0,max_half.size()-1);
}
}
}
double GetMedian()
{
if(min_half.size()==max_half.size()+1){
return min_half[0];
}
else
return 0.5*min_half[0]+0.5*max_half[0];
}
void HeapAdjustMax(vector<int>&a,int start,int end){
if(start>=end)
return ;
for(int i =end;i>=start;i--){
int left = 2*i+1;
int right= 2*i+2;
if(left<=end){
if(right<=end){
if(a[right]>a[left] && a[right]>a[i])
swap(a[i],a[right]);
else if(a[left]>a[i] && a[left]>a[right])
swap(a[i],a[left]);
}
else
if(a[left]>a[i])
swap(a[i],a[left]);
}
}
}
void HeapAdjustMin(vector<int>&a,int start,int end){
if(start>=end)
return ;
for(int i =end;i>=start;i--){
int left = 2*i+1;
int right= 2*i+2;
if(left<=end){
if(right<=end){
if(a[right]<a[left] && a[right]<a[i])
swap(a[i],a[right]);
else if(a[left]<a[i] && a[left]<a[right])
swap(a[i],a[left]);
}
else
if(a[left]<a[i])
swap(a[i],a[left]);
}
}
}