利用堆計算中位數


作業: 要求輸入$i$個數字時候計算這$i$個數字的中位數。

堆的實現利用了c++的make_heap(),sort_heap函數,類似優先隊列。

1. 最小堆的實現代碼:

/**************最小堆**********/
class MinHeap
{
public:
    void createHeap()
    {
        make_heap(heap.begin(), heap.end()); //堆化
        sort_heap(heap.begin(), heap.end());//排序
    }
/**************每次插入一個元素后需要對整體進行排序,維持優先序列特性*****************/
    void push(int i)
    {
        heap.push_back(i);//插入
        createHeap();//排序,最小值為第一個元素
    }
    int top()
    {
        return heap[0];//返回最小值
    }
/***************返回最最小值中的最后一個元素**************/
    int back()
    {
        int a = heap[heap.size()-1];
//        heap.pop_back();
        return a;
    }
    int size()
    {
        return heap.size();
    }
    void print()
    {
        for(auto i : heap)
        {
            cout << i << " ";
        }
        cout << endl;
    }
/**************刪除最后的一個元素,即最小堆中最大元素************/
    void pop()
    {
        heap.pop_back();
    }
public:
    vector<int> heap;
};
View Code

2. 最大堆的實現代碼:

class MaxHeap
{
public:
    void createHeap()
    {
        make_heap(heap.begin(), heap.end());
        sort_heap(heap.begin(), heap.end());
        reverse(heap.begin(), heap.end());//首元素為最大一個元素
    }
/**************每次插入一個元素后需要對整體進行排序,維持優先序列特性*****************/
    void push(int i)
    {
        heap.push_back(i);
        createHeap();
    }
/************返回最大的元素************/
    int top()
    {
        return heap[0];        
    }
    int back()
    {
        int a = heap[heap.size()-1];
//        heap.pop_back();
        return a;
    }
/*****************刪除最后一個元素********************/
    void pop()
    {
        heap.pop_back();
    }
    int size()
    {
        return heap.size();
    }
    void print()
    {
        for(auto i : heap)
        {
            cout << i << " ";
        }
        cout << endl;
    }
public:
    vector<int> heap;
};
View Code

3. 求中位數的步驟:輸入第i個數字時:

(1)  i個元素中較大值的一半放在最大堆中,較小的一半部分放在最小堆中

(2) 需要維持兩個堆的大小平衡。

(3) 中位數分布在最大堆的尾元素和最小堆的尾元素。

(4) 插入元素j時,j > Max_heap_min,放入最大堆, j < Min_heap_max,放入最小堆。

(5)分布在兩個值之間則隨便放,單需要控制兩個堆的平衡。

c++代碼如下:

/****************輸入第i個元素時,計算此時的i個元素的中位數****************/
class Median
{
public:
    void get_data(MaxHeap &maxheap, MinHeap &minheap)
    {
        ifstream fin("Median.txt");
        string line;
        stringstream stream;
        int count = 1;
        while(getline(fin, line))
        {
            int data;
            stream.clear();
            stream << line;
            stream >> data;
            _storage.push_back(data);    
            median(data, maxheap, minheap);
            count ++;
        }
    }

    void median(int data, MaxHeap &maxheap, MinHeap &minheap)
    {    
        if(_storage.size() == 1) //只有一個元素的情況
        {
            _median.push_back(data);
        } else if(_storage.size() == 2) { //只有兩個元素
            if(_storage[0] < _storage[1])
            {
                _median.push_back(_storage[0]);
                maxheap.heap.push_back(_storage[1]);
                minheap.heap.push_back(_storage[0]);
            } else {
                _median.push_back(_storage[1]);
                maxheap.heap.push_back(_storage[0]);
                minheap.heap.push_back(_storage[1]);
            }
        } else { //兩個以上元素
            int max = minheap.back();
            int min = maxheap.back();
            if(data > min)
            {
                maxheap.push(data);
            } else {
                minheap.push(data);
            }    
            balance(maxheap, minheap);    
            if(minheap.size() >= maxheap.size())
            {
                _median.push_back( minheap.back() );
            } else {
                _median.push_back( maxheap.back() );
            }
        }
    }
/*******************保持兩個堆數目的平衡*******************/    
    void balance(MaxHeap &maxheap, MinHeap &minheap)
    {
        int size1 = maxheap.size();
        int size2 = minheap.size();
        if(size1 - size2 == 2)    
        {
        //取出最大堆中最后一個元素放入最小堆
            int temp = maxheap.back();        
            maxheap.pop();
            minheap.push(temp);
        } else if (size2 - size1 == 2){
            int temp = minheap.back();//最后一個元素
            minheap.pop();//刪除最后一個元素
            maxheap.push(temp);//將最后一個元素放入最大堆
        } else {
            ;        
        }
    }

    void write()
    {
        ofstream fout;
        fout.open("output.txt");
        for(int i = 0; i < _median.size(); i++)
        {
            fout << "[" << i << "]:" << _median[i] << endl;
        }

    }
    void modo()
    {
        int sum = 0;
        for(auto i : _median)
        {
            sum += i;
        }
        cout << sum % 10000;
    }
public:
    vector<int> _median;
    vector<int> _storage;
};
View Code

 完整代碼:
https://github.com/Shinered/Median-/blob/master/Median.cpp


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM