查找C++無序數列中位數
1.將無序數列轉化爲有序數列,然後直接通過索引找到中位數
2.已知中位數 要求左邊小於(大於)中位數,右邊大於(小於)中位數,且左邊數列大小等於右邊數列大小 。 而對左邊數列或者右邊數列數值的排列順序無要求。
所以,我們可以採用優先隊列進行解決。
代碼實現
#include<iostream>
#include<queue>//優先隊列
#include<vector>
#include<assert.h>
#include<list>
//利用優先隊列實現,使得堆頂左邊都比堆頂大,其餘未入隊列的數據全都比堆頂小,隊列的大小應該爲一半。
using namespace std;
template<class T>
T findMidle(const T *arr,int size)
{
assert(arr);
int len=0;
//優先隊列
priority_queue<int,vector<int>,greater<int> > q;//從大到小
if(size&1)//奇數
{
len=(size+1)/2;
//將局部數據放入隊列,pop爲局部最小
for(int i=0;i<len;++i)
{
q.push(arr[i]);
}
//大於堆頂的push進入隊列,使得堆頂的左邊比堆頂大,右邊比堆頂小,此時堆頂爲中位數
for(int i=len;i<size;++i)
{
if(q.top()<arr[i])
{
q.pop();
q.push(arr[i]);
}
}
return q.top();
}
else//偶數
{
len=size/2;
//優先隊列
//priority_queue<int,vector<int>,greater<int>()> q;//從大到小
//將局部數據放入隊列,pop爲局部最小
for(int i=0;i<len;++i)
{
q.push(arr[i]);
}
//大於堆頂的push進入隊列,使得堆頂的左邊比堆頂大,右邊比堆頂小,此時堆頂爲中位數
int flag=0;//存儲最後一次pop出來的數據
for(int i=len;i<size;++i)
{
if(q.top()<arr[i])
{
flag=q.top();
q.pop();
q.push(arr[i]);
}
}
return (q.top()+flag)/2;
}
}
void test01()
{
//準備數據
int arr[]={10,20,12,16,15,4,8,10};//偶數重複, 4,8,10,10,12,15,16,20 中位數:11
//int arr1[]={10,20,12,16,15,4,10};//奇數重複, 中位數:12
int len=sizeof(arr)/sizeof(int);
int ret=findMidle<int>(arr,len);
cout<<"the middle is : "<<ret<<endl;
}
int main()
{
test01();
system("pause");
return 0;
}