设有n个互不相同的元素x1,x2,…xk,每个元素xi带有一个权值wi,且∑ni=1wi=1。若元素xk满足∑(xi<xk)wi≤12且∑(xi>xk)wi≤12,则称元素xk为x1,x2,…,xn的带权中位数。请编写一个算法(C++语言),能够在最坏情况下用O(n)时间找出n个元素的带权中位数
输入:
10
719 449 446 981 431 993 919 389 549 453
0.01757775 0.02028202 0.16863048 0.07320842 0.16283562
0.16167665 0.14970060 0.04095036 0.12806645 0.07707166
结果:
549
#include<iostream>
#include<stdlib.h>
#include<time.h>
using namespace std;
struct Element{
int value; //元素值
double weight; //权重值
};
//交换元素位置
void swap(Element *index, int p, int r)
{
Element tmp=index[p];
index[p] = index[r];
index[r] = tmp;
}
//划分数组
int Partition(Element *index, int p, int r)
{
int less = p;
int pivot = p + rand() % (r - p);
for(int i = p; i <= r; i++){
if( index[i].value < index[pivot].value ){
if( less == pivot )
pivot = i;
swap(index,less,i);
less++;
}
}
swap(index,less,pivot);
return less;
}
//求指定数组的权值之和
double getSumWeight(Element *index, int p, int r)
{
int i;
double sum = 0;
for(i=p; i<r+1; i++)
{
sum += index[i].weight;
}
return sum;
}
int SelectWeightMedian(Element *index, int p, int r)
{
if(p==r)
{
return index[p].value;
}
int pivotIndex = Partition(index, p, r); //划分数组,并返回基准值位置
double leftWeight = getSumWeight(index, p, pivotIndex-1);
double rightWeight = getSumWeight(index, pivotIndex+1, r);
if(leftWeight<=0.5&&rightWeight<=0.5)
return index[pivotIndex].value;
else if(leftWeight>rightWeight)
{
index[pivotIndex].weight += rightWeight;
return SelectWeightMedian(index, p, pivotIndex);
}
else
{
index[pivotIndex].weight += leftWeight;
return SelectWeightMedian(index, pivotIndex, r);
}
}
int main()
{
srand((int)time(0));
int lens, i;
cin>>lens;
Element *index = new Element[lens];
//录入数据
for(i=0; i<lens; i++){
cin>>index[i].value;
}
for(i=0; i<lens; i++){
cin>>index[i].weight;
}
cout<<SelectWeightMedian(index, 0, lens-1);
return 0;
}