C++ 查找中位數

查找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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章