C++默认大小根堆priority_queue求中位数

以前实现大小根堆总要自己写代码,循环父节点和孩子节点比大小换位置,今天看到C++中有默认的大小根堆实现

// 大根堆
priority_queue<type> BigRoot;
// 小根堆
priority_queue<type, vector<type>, greater<type>> SmallRoot;

当然如果全是正数的话,小根堆实现比较难记可以直接存成负数。

应用
Find Median from Data Stream 找出数据流的中位数

Median is the middle value in an ordered integer list. If the size of the list is even, there is no middle value. So the median is the mean of the two middle value.
Examples:
[2,3,4] , the median is 3
[2,3], the median is (2 + 3) / 2 = 2.5
Design a data structure that supports the following two operations:
void addNum(int num) - Add a integer number from the data stream to the data structure.
double findMedian() - Return the median of all elements so far.

For example:
add(1)
add(2)
findMedian() -> 1.5
add(3)
findMedian() -> 2

思路
既然要求中位数,如果数据有序最好了直接索引取值就好了
那么如何维持一个有序数据流?
1)二分插入
2)考虑把有序数组从中间切开[minpart | maxpart],维持一个大根堆存minpart和一个小根堆存maxpart,两堆top节点必然存放有中位数
比如[4,2,3,1,5],我们希望最终大根堆存[3,2,1],小根堆存[4,5],最终返回大根堆top
存的过程为每次新元素插入大根堆,大根堆的最大值top插入小根堆,如果小根堆size大于大根堆则把小根堆top移入大根堆
插入过程为:

step1. 大根堆 4 小根堆 null
step2. 大根堆 2 小根堆 4
step3. 大根堆 3,2 小根堆 4
step4. 大根堆 2,1 小根堆 4,3
step5. 大根堆 3,2,1 小根堆 5,4

代码

class MedianFinder {
public:
    void adjust(int num) {
    	minpart.push(num);
    	// 存成负数大根堆变小根堆
    	maxpart.push(-minpart.top());
    	minpart.pop();
    	if(minpart.size() < maxpart.size()) {
    		// maxpart中存的是负数,minpart中存的是正数
    		minpart.push(-maxpart.top());
    		maxpart.pop();
    	}
    }
    double findMedian() {
        return minpart.size() > maxpart.size() ? minpart.top() : 0.5 *(minpart.top() - maxpart.top());
    }

private:
    priority_queue<long> minpart, maxpart;
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值